home *** CD-ROM | disk | FTP | other *** search
/ ETO Development Tools 2 / ETO Development Tools 2.iso / Tools - Objects / MacApp / MacApp CD Release / MacApp 2.0.1 (Many Libraries) / Libraries / UGridView.inc1.p < prev    next >
Encoding:
Text File  |  1990-10-25  |  73.2 KB  |  2,818 lines  |  [TEXT/MPS ]

  1. {$P}
  2. {[a-,body+,h-,o=100,r+,rec+,t=4,u+,#+,j=20/57/1$,n-]}
  3. { UGridView.inc1.p }
  4. { Copyright © 1987-1990 by Apple Computer Inc. All rights reserved. }
  5.  
  6. {--------------------------------------------------------------------------------------------------}
  7. {$S GVInit}
  8.  
  9. PROCEDURE InitUGridView;
  10.  
  11.     BEGIN
  12.     IF qTemplateViews THEN
  13.         BEGIN
  14.         { So the linker doesn't dead strip these }
  15.         IF gDeadStripSuppression THEN
  16.             BEGIN
  17.             IF Member(TObject(NIL), TGridView) THEN;
  18.             IF Member(TObject(NIL), TTextGridView) THEN;
  19.             IF Member(TObject(NIL), TTextListView) THEN;
  20.             END;
  21.  
  22.         RegisterStdType('TGridView', kStdGridView);
  23.         RegisterStdType('TTextGridView', kStdTextGridView);
  24.         RegisterStdType('TTextListView', kStdTextListView);
  25.         END;
  26.  
  27.     pPixelsToHighlight := MakeNewRgn;
  28.     pPreviousSelection := MakeNewRgn;
  29.     pDifference := MakeNewRgn;
  30.     pVisibleCells := MakeNewRgn;
  31.     pInvalidateRgn := MakeNewRgn;
  32.     gUGridViewInitialized := TRUE;
  33.     END;
  34.  
  35. {--------------------------------------------------------------------------------------------------}
  36. {$S GVOpen}
  37.  
  38. PROCEDURE TRunArray.IRunArray;
  39.  
  40.     BEGIN
  41.     IObject;
  42.  
  43.     fNoOfItems := 0;
  44.     fNoOfChunks := 0;
  45.     fTotal := 0;
  46.     fLastItem := 0;
  47.     fLastChunk := 0;
  48.     fLastTotal := 0;
  49.     fLastIndex := 1;
  50.     fChunks := ChunkArrayHandle(NewPermHandle(0));
  51.     FailNIL(fChunks);
  52.     END;
  53.  
  54. {--------------------------------------------------------------------------------------------------}
  55. {$S GVClose}
  56.  
  57. PROCEDURE TRunArray.Free; OVERRIDE;
  58.  
  59.     BEGIN
  60.     Handle(fChunks) := DisposeIfHandle(fChunks);        { Blow chunks }
  61.  
  62.     INHERITED Free;
  63.     END;
  64.  
  65. {--------------------------------------------------------------------------------------------------}
  66. {$S GVNonRes}
  67.  
  68. PROCEDURE TRunArray.DeleteItems(firstItem, noOfItems: INTEGER);
  69.  
  70.     VAR
  71.         offset:             LONGINT;
  72.         result:             LONGINT;
  73.         i:                    INTEGER;
  74.         num:                INTEGER;
  75.         theTotal:            LONGINT;
  76.         Index:                INTEGER;
  77.  
  78.     BEGIN
  79.     IF NOT FindChunk(firstItem, num, Index, theTotal) THEN
  80.         BEGIN
  81.         {$IFC qDebug}
  82.         ProgramBreak(ConcatNumber('Unable to find chunk for item ', firstItem));
  83.         {$ENDC}
  84.         EXIT(DeleteItems);
  85.         END;
  86.  
  87.     FOR i := 1 TO noOfItems DO
  88.         BEGIN
  89.         fTotal := fTotal - fChunks^^[num].value;
  90.  
  91.         fChunks^^[num].count := fChunks^^[num].count - 1;
  92.  
  93.         IF (fChunks^^[num].count < Index) THEN
  94.             BEGIN
  95.             IF (fChunks^^[num].count = 0) THEN
  96.                 BEGIN
  97.                 { need to delete that chunk }
  98.                 offset := IntMultiply(num, SIZEOF(RunArrayChunk));
  99.                 result := Munger(Handle(fChunks), offset, NIL, SIZEOF(RunArrayChunk), @result, 0);
  100.                 FailMemError;
  101.                 fNoOfChunks := fNoOfChunks - 1;
  102.  
  103.                 { Thanks JDR 10/28/89 }
  104.                 { see if we can consolidate chunks }
  105.                 IF (num > 0) & (num < fNoOfChunks) & (fChunks^^[num - 1].value =
  106.                    fChunks^^[num].value) THEN
  107.                     BEGIN
  108.                     Index := fChunks^^[num - 1].count + 1;
  109.                     fChunks^^[num - 1].count := fChunks^^[num - 1].count + fChunks^^[num].count;
  110.                     { need to delete that chunk }
  111.                     result := Munger(Handle(fChunks), offset, NIL, SIZEOF(RunArrayChunk), @result,
  112.                                      0);
  113.                     FailMemError;
  114.                     num := num - 1;
  115.                     fNoOfChunks := fNoOfChunks - 1;
  116.                     END;
  117.                 END
  118.             ELSE
  119.                 num := num + 1;
  120.             Index := 1;
  121.             END;
  122.         END;
  123.  
  124.     fNoOfItems := fNoOfItems - noOfItems;
  125.  
  126.     { reset the cache }
  127.     fLastItem := 0;
  128.     fLastChunk := 0;
  129.     fLastTotal := 0;
  130.     fLastIndex := 1;
  131.     END;
  132.  
  133. {--------------------------------------------------------------------------------------------------}
  134. {$S GVFields}
  135.  
  136. PROCEDURE TRunArray.Fields(PROCEDURE DoToField(fieldName: Str255;
  137.                                                fieldAddr: Ptr;
  138.                                                fieldType: INTEGER)); OVERRIDE;
  139.  
  140.     VAR
  141.         aString, numString: Str255;
  142.         i:                    INTEGER;
  143.  
  144.     BEGIN
  145.     DoToField('TRunArray', NIL, bClass);
  146.     DoToField('fNoOfItems', @fNoOfItems, bInteger);
  147.     DoToField('fNoOfChunks', @fNoOfChunks, bInteger);
  148.     DoToField('fTotal', @fTotal, bLongInt);
  149.     DoToField('fLastItem', @fLastItem, bInteger);
  150.     DoToField('fLastChunk', @fLastChunk, bInteger);
  151.     DoToField('fLastTotal', @fLastTotal, bLongInt);
  152.     DoToField('fLastIndex', @fLastIndex, bInteger);
  153.  
  154.   { !!! When these come from the dynamic area remember to put the field in the DynamicField method }
  155.     FOR i := 0 TO fNoOfChunks - 1 DO
  156.         BEGIN
  157.         NumToString(i, numString);
  158.         aString := Concat('count[', numString, ']');
  159.         DoToField(aString, @fChunks^^[i].count, bInteger);
  160.         aString := Concat('value[', numString, ']');
  161.         DoToField(aString, @fChunks^^[i].value, bInteger);
  162.         END;
  163.     INHERITED Fields(DoToField);
  164.     END;
  165.  
  166. {--------------------------------------------------------------------------------------------------}
  167. {$S GVRes}
  168. {$Push} {$OV-}                                            {!!!SRF remove this line when the compiler
  169.                                                          gets smarter }
  170.  
  171. FUNCTION TRunArray.FindChunk(item: INTEGER;
  172.                              VAR chunk, indexInChunk: INTEGER;
  173.                              VAR theTotal: LONGINT): BOOLEAN;
  174.  
  175.     VAR
  176.         thisItem:            INTEGER;
  177.         count:                INTEGER;
  178.         delta:                INTEGER;
  179.  
  180.     BEGIN
  181.     IF (fNoOfChunks <= 0) | (item > fNoOfItems) | (item <= 0) THEN
  182.         BEGIN
  183.         chunk := 0;
  184.         theTotal := 0;
  185.         indexInChunk := 0;
  186.         FindChunk := FALSE;
  187.         item := 0;
  188.         END
  189.     ELSE IF (item = fLastItem) THEN
  190.         BEGIN                                            { check for the very easy case }
  191.         chunk := fLastChunk;
  192.         theTotal := fLastTotal;
  193.         indexInChunk := fLastIndex;
  194.         FindChunk := TRUE;
  195.         END
  196.     ELSE
  197.         BEGIN
  198.         delta := ABS(item - fLastItem);
  199.  
  200.         IF (delta >= item) | (item <= fChunks^^[0].count) THEN
  201.             BEGIN                                        { start from the first chunk }
  202.             chunk := 0;
  203.             theTotal := 0;
  204.             thisItem := 0;
  205.             END
  206.         ELSE IF (delta > (fNoOfItems - item + 1)) THEN
  207.             BEGIN                                        { start from the end chunk }
  208.             chunk := fNoOfChunks - 1;
  209.             count := fChunks^^[chunk].count;
  210.             theTotal := fTotal - IntMultiply(count, fChunks^^[chunk].value);
  211.             thisItem := fNoOfItems - count;
  212.             END
  213.         ELSE
  214.             BEGIN                                        { start from the previous values }
  215.             chunk := fLastChunk;
  216.             theTotal := fLastTotal;
  217.             thisItem := fLastItem - fLastIndex;
  218.             END;
  219.  
  220.         IF item > thisItem THEN
  221.             BEGIN
  222.             WHILE ((thisItem + fChunks^^[chunk].count) < item) DO
  223.                 BEGIN
  224.                 count := fChunks^^[chunk].count;
  225.                 theTotal := theTotal + IntMultiply(count, fChunks^^[chunk].value);
  226.                 thisItem := thisItem + count;
  227.                 chunk := chunk + 1;
  228.                 END;
  229.             END
  230.         ELSE
  231.             BEGIN
  232.             REPEAT
  233.                 chunk := chunk - 1;
  234.                 count := fChunks^^[chunk].count;
  235.                 theTotal := theTotal - IntMultiply(count, fChunks^^[chunk].value);
  236.                 thisItem := thisItem - count;
  237.             UNTIL (thisItem < item);
  238.             END;
  239.         indexInChunk := item - thisItem;
  240.         FindChunk := TRUE;
  241.         END;
  242.     { cache the last values }
  243.     fLastItem := item;
  244.     fLastChunk := chunk;
  245.     fLastTotal := theTotal;
  246.     fLastIndex := indexInChunk;
  247.     END;
  248. {$Pop}
  249.  
  250. {--------------------------------------------------------------------------------------------------}
  251. {$S GVRes}
  252.  
  253. FUNCTION TRunArray.FindItem(theTotal: LONGINT): INTEGER;
  254.  
  255.     VAR
  256.         i:                    INTEGER;
  257.         runningCount:        INTEGER;
  258.  
  259.     BEGIN
  260.     FindItem := 0;
  261.     IF (theTotal >= 0) & (theTotal <= fTotal) & (fNoOfChunks > 0) THEN
  262.         IF fNoOfChunks = 1 THEN
  263.             BEGIN
  264.             IF fChunks^^[0].value > 0 THEN
  265.                 FindItem := Min(((theTotal - 1) DIV fChunks^^[0].value) + 1, fNoOfItems);
  266.             END
  267.         ELSE IF theTotal = 0 THEN
  268.             FindItem := 1
  269.         ELSE
  270.             BEGIN
  271.             theTotal := theTotal + 1;
  272.             runningCount := 0;
  273.             FOR i := 0 TO fNoOfChunks - 1 DO
  274.                 WITH fChunks^^[i] DO
  275.                     BEGIN
  276.                     theTotal := theTotal - IntMultiply(value, count);
  277.                     runningCount := runningCount + count;
  278.                     IF theTotal <= 0 THEN
  279.                         BEGIN
  280.                         FindItem := runningCount + (theTotal DIV value);
  281.                         EXIT(FindItem);
  282.                         END;
  283.                     END;
  284.             FindItem := fNoOfItems;
  285.             END;
  286.     END;
  287.  
  288. {--------------------------------------------------------------------------------------------------}
  289. {$S GVRes}
  290.  
  291. FUNCTION TRunArray.GetValue(item: INTEGER): INTEGER;
  292.  
  293.     VAR
  294.         num:                INTEGER;
  295.         theTotal:            LONGINT;
  296.         Index:                INTEGER;
  297.  
  298.     BEGIN
  299.     IF fNoOfChunks = 1 THEN
  300.         GetValue := fChunks^^[0].value
  301.     ELSE IF FindChunk(item, num, Index, theTotal) THEN
  302.         GetValue := fChunks^^[num].value
  303.     ELSE
  304.         GetValue := 0;
  305.     END;
  306.  
  307. {--------------------------------------------------------------------------------------------------}
  308. {$S GVRes}
  309.  
  310. PROCEDURE TRunArray.InsertItems(firstItem, noOfItems, value: INTEGER);
  311.  
  312.     VAR
  313.         num:                INTEGER;
  314.         theTotal:            LONGINT;
  315.         Index:                INTEGER;
  316.         oldSize:            LONGINT;
  317.         result:             LONGINT;
  318.         tempChunks:         RECORD
  319.             chunk1:             RunArrayChunk;
  320.             chunk2:             RunArrayChunk;
  321.             END;
  322.  
  323.     BEGIN
  324.     { Check if we can just increment the last size count }
  325.     IF (firstItem > fNoOfItems) & (fNoOfChunks > 0) & (fChunks^^[fNoOfChunks - 1].value =
  326.        value) THEN
  327.  
  328.         fChunks^^[fNoOfChunks - 1].count := fChunks^^[fNoOfChunks - 1].count + noOfItems
  329.  
  330.         { check if we can increment any size count }
  331.     ELSE IF FindChunk(firstItem, num, Index, theTotal) & (fChunks^^[num].value = value) THEN
  332.  
  333.         fChunks^^[num].count := fChunks^^[num].count + noOfItems
  334.  
  335.         { check if this would actually fit as the last item in the previous chunk }
  336.         { Thanks Martin Frické, 10/31/89 }
  337.     ELSE IF (num > 0) & (Index = 1) & (fChunks^^[num - 1].value = value) THEN
  338.         fChunks^^[num - 1].count := fChunks^^[num - 1].count + noOfItems
  339.  
  340.         { We need to create a new chunk, possibly two }
  341.     ELSE
  342.         BEGIN
  343.         oldSize := GetHandleSize(Handle(fChunks));
  344.         tempChunks.chunk1.value := value;
  345.         tempChunks.chunk1.count := noOfItems;
  346.  
  347.         IF (Index <= 1) | (firstItem > fNoOfItems) THEN
  348.             BEGIN                                        { need to add one chunk }
  349.             IF (firstItem > fNoOfItems) THEN
  350.                 num := fNoOfChunks;                     { add a row on the end }
  351.  
  352.             result := Munger(Handle(fChunks), IntMultiply(num, SIZEOF(RunArrayChunk)), NIL, 0,
  353.                              @tempChunks, SIZEOF(RunArrayChunk));
  354.             FailMemError;
  355.             fNoOfChunks := fNoOfChunks + 1;
  356.             END
  357.         ELSE
  358.             BEGIN
  359.             { need to add two }
  360.             tempChunks.chunk2.count := fChunks^^[num].count - Index + 1;
  361.             tempChunks.chunk2.value := fChunks^^[num].value;
  362.             fChunks^^[num].count := Index - 1;
  363.             result := Munger(Handle(fChunks), IntMultiply(num + 1, SIZEOF(RunArrayChunk)), NIL, 0,
  364.                              @tempChunks, 2 * SIZEOF(RunArrayChunk));
  365.             FailMemError;
  366.             fNoOfChunks := fNoOfChunks + 2;
  367.             END;
  368.         IF GetHandleSize(Handle(fChunks)) <= oldSize THEN
  369.             Failure(memFullErr, 0);
  370.         END;
  371.  
  372.     { reset the cache }
  373.     fLastItem := 0;
  374.     fLastChunk := 0;
  375.     fLastTotal := 0;
  376.     fLastIndex := 1;
  377.  
  378.     fNoOfItems := fNoOfItems + noOfItems;
  379.     fTotal := fTotal + IntMultiply(noOfItems, value);
  380.     END;
  381.  
  382. {--------------------------------------------------------------------------------------------------}
  383. {$S GVRes}
  384.  
  385. FUNCTION TRunArray.SumValues(firstItem, noOfItems: INTEGER): LONGINT;
  386.  
  387.     VAR
  388.         chunk:                INTEGER;
  389.         indexInChunk:        INTEGER;
  390.         total:                LONGINT;
  391.         precedingTotal:     LONGINT;
  392.  
  393.     BEGIN
  394.     SumValues := 0;
  395.  
  396.     IF fNoOfChunks = 1 THEN
  397.         SumValues := IntMultiply(noOfItems, fChunks^^[0].value)
  398.     ELSE IF firstItem = 1 THEN
  399.         BEGIN
  400.         IF FindChunk(noOfItems, chunk, indexInChunk, total) THEN
  401.             SumValues := total + IntMultiply(indexInChunk, fChunks^^[chunk].value);
  402.         END
  403.     ELSE IF FindChunk(firstItem, chunk, indexInChunk, total) THEN
  404.         BEGIN
  405.         precedingTotal := total + IntMultiply(indexInChunk - 1, fChunks^^[chunk].value);
  406.         IF FindChunk(firstItem + noOfItems - 1, chunk, indexInChunk, total) THEN
  407.             SumValues := total + IntMultiply(indexInChunk, fChunks^^[chunk].value) - precedingTotal;
  408.         END;
  409.     END;
  410.  
  411. {--------------------------------------------------------------------------------------------------}
  412. {$S GVOpen}
  413.  
  414. PROCEDURE TGridView.IGridView(itsDocument: TDocument;    { Its document }
  415.                               itsSuperView: TView;        { Its parent view }
  416.                               itsLocation: VPoint;        { Top, Left in parent's coords }
  417.                               itsSize: VPoint;            { Ignored for SizeVariable}
  418.                               itsHSizeDet, itsVSizeDet: SizeDeterminer; { Size determiners }
  419.                               numOfRows: INTEGER;        { Number of rows initially }
  420.                               numOfCols: INTEGER;        { Number of columns initially }
  421.                               rowHeight: INTEGER;        { Height of initial rows }
  422.                               colWidth: INTEGER;        { Height of initial columns }
  423.                               adornRows: BOOLEAN;        { Adornment for Rows? }
  424.                               adornCols: BOOLEAN;        { Adornment for Columns? }
  425.                               rowInset: INTEGER;        { horizontal space between cells }
  426.                               colInset: INTEGER;        { vertical space between cells }
  427.                               singleSelection: BOOLEAN); { single cell selection? }
  428.  
  429.     VAR
  430.         aRunArray:            TRunArray;
  431.         fi:                    FailInfo;
  432.         
  433.     PROCEDURE HandleFailure (error: OSErr; message: LONGINT);
  434.         
  435.         BEGIN
  436.         Free;
  437.         END;
  438.  
  439.     BEGIN
  440.     fSelections := NIL;
  441.     fHLRegion := NIL;
  442.     fTempSelections := NIL;
  443.     fColWidths := NIL;
  444.     fRowHeights := NIL;
  445.  
  446.     {$IFC qDebug}
  447.     IF NOT gUGridViewInitialized THEN
  448.         BEGIN
  449.         ProgramBreak('InitUGridView must be called before creating a grid view.');
  450.         Failure(noErr, 0);
  451.         END;
  452.     {$ENDC}
  453.  
  454.     fNumOfRows := 0;
  455.     fNumOfCols := 0;
  456.  
  457.     fAdornRows := adornRows;
  458.     fAdornCols := adornCols;
  459.  
  460.     { Make sure the insets are evenly divided between top/bottom or left/right }
  461.     IF ODD(rowInset) THEN
  462.         fRowInset := rowInset + 1
  463.     ELSE
  464.         fRowInset := rowInset;
  465.  
  466.     IF ODD(colInset) THEN
  467.         fColInset := colInset + 1
  468.     ELSE
  469.         fColInset := colInset;
  470.  
  471.     IView(itsDocument, itsSuperView, itsLocation, itsSize, itsHSizeDet, itsVSizeDet);
  472.  
  473.     CatchFailures(fi, HandleFailure);
  474.     
  475.     New(aRunArray);
  476.     FailNIL(aRunArray);
  477.     fColWidths := aRunArray;
  478.     fColWidths.IRunArray;
  479.  
  480.     New(aRunArray);
  481.     FailNIL(aRunArray);
  482.     fRowHeights := aRunArray;
  483.     fRowHeights.IRunArray;
  484.  
  485.     fSelections := MakeNewRgn;                            { region to hold current selections }
  486.     fHLRegion := MakeNewRgn;                            { region to hold current highlighted cells }
  487.     fTempSelections := MakeNewRgn;                        { used by SetSelectionRect }
  488.  
  489.     fSingleSelection := singleSelection;
  490.  
  491.     IF (numOfCols > 0) THEN
  492.         InsColFirst(numOfCols, colWidth);
  493.     IF (numOfRows > 0) THEN
  494.         InsRowFirst(numOfRows, rowHeight);
  495.  
  496.     Success(fi);
  497.     END;
  498.  
  499. {--------------------------------------------------------------------------------------------------}
  500. {$S GVOpen}
  501.  
  502. PROCEDURE TGridView.IRes(itsDocument: TDocument;
  503.                          itsSuperView: TView;
  504.                          VAR itsParams: Ptr); OVERRIDE;
  505.  
  506.     VAR
  507.         aRunArray:            TRunArray;
  508.         fi:                    FailInfo;
  509.         
  510.     PROCEDURE HandleFailure (error: OSErr; message: LONGINT);
  511.         
  512.         BEGIN
  513.         Free;
  514.         END;
  515.  
  516.     BEGIN
  517.     fSelections := NIL;
  518.     fHLRegion := NIL;
  519.     fTempSelections := NIL;
  520.     fColWidths := NIL;
  521.     fRowHeights := NIL;
  522.     
  523.     {$IFC qDebug}
  524.     IF NOT gUGridViewInitialized THEN
  525.         BEGIN
  526.         ProgramBreak('InitUGridView must be called before creating a grid view.');
  527.         Failure(noErr, 0);
  528.         END;
  529.     {$ENDC}
  530.  
  531.     INHERITED IRes(itsDocument, itsSuperView, itsParams);
  532.  
  533.     WITH GridViewTemplatePtr(itsParams)^ DO
  534.         BEGIN
  535.         fNumOfRows := 0;
  536.         fNumOfCols := 0;
  537.  
  538.         fAdornRows := adornRows;
  539.         fAdornCols := adornCols;
  540.  
  541.         { Make sure the insets are evenly divided between top/bottom or left/right }
  542.         IF ODD(rowInset) THEN
  543.             fRowInset := rowInset + 1
  544.         ELSE
  545.             fRowInset := rowInset;
  546.  
  547.         IF ODD(colInset) THEN
  548.             fColInset := colInset + 1
  549.         ELSE
  550.             fColInset := colInset;
  551.  
  552.         fSingleSelection := singleSelection;
  553.         
  554.         
  555.         CatchFailures(fi, HandleFailure);
  556.  
  557.         New(aRunArray);
  558.         FailNIL(aRunArray);
  559.         fColWidths := aRunArray;
  560.         fColWidths.IRunArray;
  561.  
  562.         New(aRunArray);
  563.         FailNIL(aRunArray);
  564.         fRowHeights := aRunArray;
  565.         fRowHeights.IRunArray;
  566.  
  567.         fSelections := MakeNewRgn;                        { region to hold current selections }
  568.         fHLRegion := MakeNewRgn;                        { region to hold current highlighted cells }
  569.         fTempSelections := MakeNewRgn;                    { used by SetSelectionRect }
  570.  
  571.         IF (numOfCols > 0) THEN
  572.             InsColFirst(numOfCols, colWidth);
  573.         IF (numOfRows > 0) THEN
  574.             InsRowFirst(numOfRows, rowHeight);
  575.  
  576.         END;
  577.  
  578.     OffsetPtr(itsParams, SIZEOF(GridViewTemplate));
  579.     
  580.     Success(fi);
  581.     END;
  582.  
  583. {--------------------------------------------------------------------------------------------------}
  584. {$S GVNonRes}
  585.  
  586. PROCEDURE TGridView.WRes(theResource: ViewRsrcHndl;
  587.                          VAR itsParams: Ptr); OVERRIDE;
  588.  
  589.     VAR
  590.         gvPtr:                GridViewTemplatePtr;
  591.  
  592.     BEGIN
  593.     INHERITED WRes(theResource, itsParams);
  594.  
  595.     gvPtr := GridViewTemplatePtr(ExpandPtr(theResource, itsParams, SIZEOF(GridViewTemplate)));
  596.  
  597.     WITH gvPtr^ DO
  598.         BEGIN
  599.         numOfRows := fNumOfRows;
  600.         numOfCols := fNumOfCols;
  601.         IF fNumOfRows > 0 THEN
  602.             rowHeight := GetRowHeight(1)
  603.         ELSE
  604.             rowHeight := 0;
  605.         IF fNumOfCols > 0 THEN
  606.             colWidth := GetColWidth(1)
  607.         ELSE
  608.             colWidth := 0;
  609.         rowInset := fRowInset;
  610.         colInset := fColInset;
  611.         adornRows := fAdornRows;
  612.         adornCols := fAdornCols;
  613.         singleSelection := fSingleSelection;
  614.         END;
  615.     END;
  616.  
  617. {--------------------------------------------------------------------------------------------------}
  618. {$S GVNonRes}
  619.  
  620. PROCEDURE TGridView.WriteRes(theResource: ViewRsrcHndl;
  621.                              VAR itsParams: Ptr); OVERRIDE;
  622.  
  623.     BEGIN
  624.     gWResSignature := 'grid'; gWResType := 'TGridView';
  625.     WRes(theResource, itsParams);
  626.     END;
  627.  
  628. {--------------------------------------------------------------------------------------------------}
  629. {$S GVClose}
  630.  
  631. PROCEDURE TGridView.Free; OVERRIDE;
  632.  
  633.     BEGIN
  634.     IF fSelections <> NIL THEN
  635.         DisposeRgn(fSelections);                        { Dispose regions }
  636.     fSelections := NIL;
  637.  
  638.     IF fHLRegion <> NIL THEN
  639.         DisposeRgn(fHLRegion);
  640.     fHLRegion := NIL;
  641.  
  642.     IF fTempSelections <> NIL THEN
  643.         DisposeRgn(fTempSelections);
  644.     fTempSelections := NIL;
  645.  
  646.     FreeIfObject(fColWidths);
  647.     fColWidths := NIL;
  648.  
  649.     FreeIfObject(fRowHeights);
  650.     fRowHeights := NIL;
  651.  
  652.     INHERITED Free;
  653.     END;
  654.  
  655. {--------------------------------------------------------------------------------------------------}
  656. {$S GVRes}
  657.  
  658. PROCEDURE TGridView.AllCellsDo(PROCEDURE DoToCell(aCell: GridCell));
  659.  
  660.     VAR
  661.         bounds:             Rect;
  662.  
  663.     BEGIN
  664.     SetRect(bounds, 1, 1, fNumOfCols, fNumOfRows);
  665.     EachCellDo(bounds.topLeft, bounds.botRight, DoToCell);
  666.     END;
  667.  
  668. {--------------------------------------------------------------------------------------------------}
  669. {$S GVRes}
  670.  
  671. PROCEDURE TGridView.AdornCol(aCol: INTEGER;
  672.                              area: Rect);
  673.  
  674.     BEGIN
  675.     END;
  676.  
  677. {--------------------------------------------------------------------------------------------------}
  678. {$S GVRes}
  679.  
  680. PROCEDURE TGridView.AdornRow(aRow: INTEGER;
  681.                              area: Rect);
  682.  
  683.     BEGIN
  684.     END;
  685.  
  686. {--------------------------------------------------------------------------------------------------}
  687. {$S GVRes}
  688.  
  689. PROCEDURE TGridView.CalcMinSize(VAR minSize: VPoint); OVERRIDE;
  690.  
  691.     BEGIN
  692.     INHERITED CalcMinSize(minSize);
  693.  
  694.     { Set the amount of room needed for that many items }
  695.     minSize.v := fRowHeights.fTotal;
  696.     minSize.h := fColWidths.fTotal;
  697.     END;
  698.  
  699. {--------------------------------------------------------------------------------------------------}
  700. {$S GVRes}
  701.  
  702. FUNCTION TGridView.CanSelectCell(aCell: GridCell): BOOLEAN;
  703.  
  704.     BEGIN
  705.     WITH aCell DO
  706.         CanSelectCell := (h >= 1) & (v >= 1) & (h <= fNumOfCols) & (v <= fNumOfRows);
  707.     END;
  708.  
  709. {--------------------------------------------------------------------------------------------------}
  710. {$S GVRes}
  711.  
  712. PROCEDURE TGridView.CellToVRect(aCell: GridCell;
  713.                                 VAR aRect: VRect);
  714.  
  715.     VAR
  716.         width, height:        INTEGER;
  717.  
  718.     BEGIN
  719.     IF (aCell.h < 1) | (aCell.v < 1) | (aCell.h > fNumOfCols) | (aCell.v > fNumOfRows) THEN
  720.         BEGIN
  721.         {$IFC qRangeCheck AND qDebug}
  722.         Writeln('aCell.h = ', aCell.h: 6, ' fNumOfCols = ', fNumOfCols: 6);
  723.         Writeln('aCell.v = ', aCell.v: 6, ' fNumOfRows = ', fNumOfRows: 6);
  724.         ProgramBreak('Range Check in CellToVRect');
  725.         {$ENDC}
  726.         aRect := gZeroVRect;
  727.         END
  728.     ELSE                                                { all the params look OK }
  729.         BEGIN
  730.         width := fColWidths.GetValue(aCell.h);
  731.         IF fColWidths.fNoOfChunks = 1 THEN
  732.             aRect.left := IntMultiply(width, aCell.h - 1)
  733.         ELSE
  734.             aRect.left := fColWidths.SumValues(1, aCell.h - 1);
  735.         aRect.right := aRect.left + width;
  736.  
  737.         height := fRowHeights.GetValue(aCell.v);
  738.         IF fRowHeights.fNoOfChunks = 1 THEN
  739.             aRect.top := IntMultiply(height, aCell.v - 1)
  740.         ELSE
  741.             aRect.top := fRowHeights.SumValues(1, aCell.v - 1);
  742.         aRect.bottom := aRect.top + height;
  743.         END;
  744.     END;
  745.  
  746. {--------------------------------------------------------------------------------------------------}
  747. {$S GVRes}
  748.  
  749. PROCEDURE TGridView.ColToVRect(aCol: INTEGER;
  750.                                numOfCols: INTEGER;
  751.                                VAR aRect: VRect);
  752.  
  753.     VAR
  754.         width:                LONGINT;
  755.         leftEdge:            LONGINT;
  756.  
  757.     BEGIN
  758.     IF (aCol < 1) | (numOfCols < 1) | (aCol + numOfCols - 1 > fNumOfCols) THEN
  759.         BEGIN
  760.         {$IFC qDebug AND qRangeCheck}
  761.         Writeln('fNumOfCols = ', fNumOfCols: 1, '  aCol = ', aCol: 1);
  762.         ProgramBreak('Range Check in ColToVRect');
  763.         {$ENDC}
  764.         SetVRect(aRect, 0, 0, 0, 0);
  765.         END
  766.     ELSE                                                { all the params look OK }
  767.         BEGIN
  768.         IF (fColWidths.fNoOfChunks = 1) THEN            { only one column height }
  769.             BEGIN
  770.             width := GetColWidth(1);
  771.             leftEdge := IntMultiply(width, aCol - 1);
  772.             width := IntMultiply(width, numOfCols);
  773.             END
  774.         ELSE
  775.             BEGIN
  776.             leftEdge := fColWidths.SumValues(1, aCol - 1);
  777.             width := fColWidths.SumValues(aCol, numOfCols);
  778.             END;
  779.  
  780.         SetVRect(aRect, leftEdge, 0, leftEdge + width, fRowHeights.fTotal);
  781.         END;
  782.     END;
  783.  
  784. {--------------------------------------------------------------------------------------------------}
  785. {$S GVRes}
  786.  
  787. PROCEDURE TGridView.CellsToPixels(theCells, thePixels: RgnHandle);
  788.  
  789.     VAR
  790.         cellBounds:         Rect;
  791.         visibleRect:        Rect;
  792.         visibleVRect:        VRect;
  793.         visibleCells:        Rect;
  794.         stripRect:            Rect;
  795.         aCell:                GridCell;
  796.         row, col:            INTEGER;
  797.         pixels:             VRect;
  798.         prevPixels:         VRect;
  799.         prevstripRect:        Rect;
  800.         direction:            VHSelect;
  801.         startOfStrip:        INTEGER;
  802.  
  803.     PROCEDURE AddStrip(endOfStrip: INTEGER);
  804.  
  805.         BEGIN
  806.         IF direction = v THEN
  807.             SetRect(stripRect, col, startOfStrip, col, endOfStrip)
  808.         ELSE
  809.             SetRect(stripRect, startOfStrip, row, endOfStrip, row);
  810.  
  811.         {$IFC qDebug}
  812.         IF gIntenseDebugging THEN
  813.             BEGIN
  814.             WrLblRect('Adding cells', stripRect);
  815.             Writeln;
  816.             END;
  817.         {$ENDC}
  818.  
  819.         IF stripRect.top = prevstripRect.top THEN
  820.             pixels.top := prevPixels.top
  821.         ELSE
  822.             BEGIN
  823.             pixels.top := fRowHeights.SumValues(1, stripRect.top - 1);
  824.             prevPixels.top := pixels.top;
  825.             END;
  826.         IF stripRect.bottom = prevstripRect.bottom THEN
  827.             pixels.bottom := prevPixels.bottom
  828.         ELSE
  829.             BEGIN
  830.             IF stripRect.bottom = stripRect.top THEN
  831.                 pixels.bottom := pixels.top + fRowHeights.GetValue(stripRect.bottom)
  832.             ELSE
  833.                 pixels.bottom := fRowHeights.SumValues(1, stripRect.bottom);
  834.             prevPixels.bottom := pixels.bottom;
  835.             END;
  836.         IF stripRect.left = prevstripRect.left THEN
  837.             pixels.left := prevPixels.left
  838.         ELSE
  839.             BEGIN
  840.             pixels.left := fColWidths.SumValues(1, stripRect.left - 1);
  841.             prevPixels.left := pixels.left;
  842.             END;
  843.         IF stripRect.right = prevstripRect.right THEN
  844.             pixels.right := prevPixels.right
  845.         ELSE
  846.             BEGIN
  847.             IF stripRect.right = stripRect.left THEN
  848.                 pixels.right := pixels.left + fColWidths.GetValue(stripRect.right)
  849.             ELSE
  850.                 pixels.right := fColWidths.SumValues(1, stripRect.right);
  851.             prevPixels.right := pixels.right;
  852.             END;
  853.  
  854.         ViewToQDRect(pixels, gTempRgn^^.rgnBBox);        { Sneaky, but we know gTempRgn is
  855.                                                          rectangular }
  856.         UnionRgn(gTempRgn, thePixels, thePixels);
  857.  
  858.         prevstripRect := stripRect;
  859.         startOfStrip := 0;
  860.         END;
  861.  
  862.     BEGIN
  863.     SetEmptyRgn(thePixels);
  864.  
  865.     IF NOT EmptyRgn(theCells) & Focus THEN
  866.         IF theCells^^.rgnSize = 10 THEN                 { the region is a rectangle }
  867.             BEGIN
  868.             cellBounds := theCells^^.rgnBBox;
  869.             SetVRect(pixels, fColWidths.SumValues(1, cellBounds.left - 1), fRowHeights.SumValues(1,
  870.                      cellBounds.top - 1), fColWidths.SumValues(1, cellBounds.right - 1),
  871.                      fRowHeights.SumValues(1, cellBounds.bottom - 1));
  872.             ViewToQDRect(pixels, thePixels^^.rgnBBox);
  873.             END
  874.         ELSE
  875.             BEGIN
  876.             { Reduce the cells to only those that are visible }
  877.             GetVisibleRect(visibleRect);
  878.             QDToViewRect(visibleRect, visibleVRect);
  879.             visibleCells.topLeft := VPointToLastCell(visibleVRect.topLeft);
  880.             visibleCells.botRight := VPointToLastCell(visibleVRect.botRight);
  881.             WITH visibleCells DO
  882.                 SetRectRgn(pVisibleCells, left, top, right + 1, bottom + 1);
  883.             SectRgn(theCells, pVisibleCells, pVisibleCells);
  884.             cellBounds := pVisibleCells^^.rgnBBox;
  885.  
  886.             {$IFC qDebug}
  887.             UseTempRgn('TGridView.CellsToPixels');
  888.             {$ENDC}
  889.             SetEmptyRgn(gTempRgn);
  890.             prevstripRect := gZeroRect;
  891.             direction := LongerSide(cellBounds);
  892.             IF direction = v THEN
  893.                 FOR col := cellBounds.left TO cellBounds.right - 1 DO
  894.                     BEGIN
  895.                     aCell.h := col;
  896.                     startOfStrip := 0;
  897.                     FOR row := cellBounds.top TO cellBounds.bottom - 1 DO
  898.                         BEGIN
  899.                         aCell.v := row;
  900.                         IF PtInRgn(aCell, pVisibleCells) THEN
  901.                             BEGIN
  902.                             IF startOfStrip = 0 THEN
  903.                                 startOfStrip := row
  904.                             END
  905.                         ELSE IF startOfStrip > 0 THEN
  906.                             AddStrip(row - 1);
  907.                         END;
  908.                     IF startOfStrip > 0 THEN
  909.                         AddStrip(cellBounds.bottom - 1);
  910.                     END
  911.             ELSE
  912.                 FOR row := cellBounds.top TO cellBounds.bottom - 1 DO
  913.                     BEGIN
  914.                     aCell.v := row;
  915.                     startOfStrip := 0;
  916.                     FOR col := cellBounds.left TO cellBounds.right - 1 DO
  917.                         BEGIN
  918.                         aCell.h := col;
  919.                         IF PtInRgn(aCell, pVisibleCells) THEN
  920.                             BEGIN
  921.                             IF startOfStrip = 0 THEN
  922.                                 startOfStrip := col
  923.                             END
  924.                         ELSE IF startOfStrip > 0 THEN
  925.                             AddStrip(col - 1);
  926.                         END;
  927.                     IF startOfStrip > 0 THEN
  928.                         AddStrip(cellBounds.right - 1);
  929.                     END;
  930.             {$IFC qDebug}
  931.             DoneWithTempRgn;
  932.             {$ENDC}
  933.             END;
  934.     END;
  935.  
  936. {--------------------------------------------------------------------------------------------------}
  937. {$S GVRes}
  938.  
  939. PROCEDURE TGridView.DoHighlightSelection(fromHL, toHL: HLState); OVERRIDE;
  940.  
  941.     BEGIN
  942.     IF NOT EmptyRgn(fHLRegion) THEN
  943.         HighlightCells(fHLRegion, fromHL, toHL)
  944.     END;
  945.  
  946. {--------------------------------------------------------------------------------------------------}
  947. {$S GVRes}
  948.  
  949. PROCEDURE TGridView.HighlightCells(theCells: RgnHandle;
  950.                                    fromHL, toHL: HLState);
  951.  
  952.     BEGIN
  953.     IF fromHL = hlDim THEN                                { GridViews don't support dim highlighting }
  954.         fromHL := hlOFF;
  955.     IF toHL = hlDim THEN
  956.         toHL := hlOFF;
  957.  
  958.     IF (fromHL <> toHL) & Focus THEN
  959.         BEGIN
  960.         CellsToPixels(theCells, pPixelsToHighlight);
  961.  
  962.         PenNormal;
  963.         UseSelectionColor;
  964.         InvertRgn(pPixelsToHighlight);                    { highlight the cells }
  965.         END;
  966.     END;
  967.  
  968. {--------------------------------------------------------------------------------------------------}
  969. {$S GVRes}
  970.  
  971. FUNCTION TGridView.DoMouseCommand(VAR theMouse: Point;
  972.                                   VAR info: EventInfo;
  973.                                   VAR hysteresis: Point): TCommand; OVERRIDE;
  974.  
  975.     VAR
  976.         aRow, aCol:         INTEGER;
  977.         aCellSelectCommand: TCellSelectCommand;
  978.  
  979.     BEGIN
  980.     DoMouseCommand := NIL;
  981.  
  982.     IF IdentifyPoint(theMouse, aRow, aCol) <> badChoice THEN
  983.         BEGIN
  984.         New(aCellSelectCommand);
  985.         FailNIL(aCellSelectCommand);
  986.         aCellSelectCommand.ICellSelectCommand(SELF, info.theShiftKey, info.theCmdKey);
  987.         DoMouseCommand := aCellSelectCommand;
  988.         END;
  989.     END;
  990.  
  991. {--------------------------------------------------------------------------------------------------}
  992. {$S GVRes}
  993.  
  994. PROCEDURE TGridView.Draw(area: Rect); OVERRIDE;
  995.  
  996.     VAR
  997.         aRect:                VRect;
  998.         bRect:                VRect;
  999.         aQDRect:            Rect;
  1000.         i:                    INTEGER;
  1001.         startCell:            GridCell;
  1002.         stopCell:            GridCell;
  1003.         viewArea:            VRect;
  1004.         colWidth:            INTEGER;
  1005.         rowHeight:            INTEGER;
  1006.         constantWidth, constantHeight: BOOLEAN;
  1007.         startCellToDraw:    GridCell;
  1008.         cellsArea:            Rect;
  1009.  
  1010.     BEGIN
  1011.     IF (fNumOfRows > 0) & (fNumOfCols > 0) THEN
  1012.         BEGIN                                            { make sure we have something to draw }
  1013.         QDToViewRect(area, viewArea);
  1014.  
  1015.         WITH viewArea DO
  1016.             BEGIN
  1017.             startCell := VPointToLastCell(topLeft);
  1018.             stopCell := VPointToLastCell(botRight);
  1019.             END;
  1020.  
  1021.         CellToVRect(startCell, aRect);
  1022.         CellToVRect(stopCell, bRect);
  1023.         bRect.topLeft := aRect.topLeft;
  1024.         ViewToQDRect(bRect, area);
  1025.  
  1026.         startCellToDraw := startCell;
  1027.         cellsArea := area;
  1028.         IF viewArea.top >= aRect.bottom - BSR(fRowInset, 1) THEN
  1029.             BEGIN
  1030.             startCellToDraw.v := startCellToDraw.v + 1;
  1031.             cellsArea.top := cellsArea.top - aRect.top + aRect.bottom;
  1032.             END;
  1033.  
  1034.         DrawRangeOfCells(startCellToDraw, stopCell, cellsArea);
  1035.  
  1036.         IF fAdornCols THEN
  1037.             BEGIN
  1038.             aQDRect := area;
  1039.  
  1040.             constantWidth := fColWidths.fNoOfChunks = 1;
  1041.             IF constantWidth THEN                        { only one width }
  1042.                 colWidth := GetColWidth(1);
  1043.  
  1044.             FOR i := startCell.h TO stopCell.h DO
  1045.                 BEGIN
  1046.                 IF constantWidth THEN
  1047.                     aQDRect.right := aQDRect.left + colWidth
  1048.                 ELSE
  1049.                     aQDRect.right := aQDRect.left + GetColWidth(i);
  1050.  
  1051.                 AdornCol(i, aQDRect);
  1052.                 aQDRect.left := aQDRect.right;
  1053.                 END;
  1054.             END;
  1055.  
  1056.         IF fAdornRows THEN
  1057.             BEGIN
  1058.             aQDRect := area;
  1059.  
  1060.             constantHeight := fRowHeights.fNoOfChunks = 1;
  1061.             IF constantHeight THEN                        { only one height }
  1062.                 rowHeight := GetRowHeight(1);
  1063.  
  1064.             FOR i := startCell.v TO stopCell.v DO
  1065.                 BEGIN
  1066.                 IF constantHeight THEN
  1067.                     aQDRect.bottom := aQDRect.top + rowHeight
  1068.                 ELSE
  1069.                     aQDRect.bottom := aQDRect.top + GetRowHeight(i);
  1070.  
  1071.                 AdornRow(i, aQDRect);
  1072.                 aQDRect.top := aQDRect.bottom;
  1073.                 END;
  1074.             END;
  1075.         END;
  1076.  
  1077.     INHERITED Draw(area);
  1078.     END;
  1079.  
  1080. {--------------------------------------------------------------------------------------------------}
  1081. {$S GVRes}
  1082.  
  1083. PROCEDURE TGridView.DrawRangeOfCells(startCell, stopCell: GridCell;
  1084.                                      aQDRect: Rect);
  1085.  
  1086.     VAR
  1087.         colWidth:            INTEGER;
  1088.         rowHeight:            INTEGER;
  1089.         i, j:                INTEGER;
  1090.         aCell:                GridCell;
  1091.         left:                INTEGER;
  1092.  
  1093.     BEGIN
  1094.  
  1095.     aQDRect.left := aQDRect.left + BSR(fColInset, 1);    { fColInset DIV 2 }
  1096.     aQDRect.top := aQDRect.top + BSR(fRowInset, 1);     { fRowInset DIV 2 }
  1097.     left := aQDRect.left;
  1098.  
  1099.     IF fColWidths.fNoOfChunks = 1 THEN                    { only one width }
  1100.         colWidth := GetColWidth(1);
  1101.     IF fRowHeights.fNoOfChunks = 1 THEN                 { only one height }
  1102.         rowHeight := GetRowHeight(1);
  1103.  
  1104.     FOR j := startCell.v TO stopCell.v DO
  1105.         BEGIN
  1106.         IF fRowHeights.fNoOfChunks = 1 THEN             { only one height }
  1107.             aQDRect.bottom := aQDRect.top + rowHeight - fRowInset
  1108.         ELSE
  1109.             aQDRect.bottom := aQDRect.top + GetRowHeight(j) - fRowInset;
  1110.  
  1111.         aQDRect.left := left;                            { start back at the left for the next row }
  1112.  
  1113.         FOR i := startCell.h TO stopCell.h DO
  1114.             BEGIN
  1115.             IF fColWidths.fNoOfChunks = 1 THEN            { only one height }
  1116.                 aQDRect.right := aQDRect.left + colWidth - fColInset
  1117.             ELSE
  1118.                 aQDRect.right := aQDRect.left + GetColWidth(i) - fColInset;
  1119.  
  1120.             aCell.h := i;
  1121.             aCell.v := j;
  1122.             DrawCell(aCell, aQDRect);
  1123.  
  1124.             aQDRect.left := aQDRect.right + fColInset;
  1125.             END;
  1126.         aQDRect.top := aQDRect.bottom + fRowInset;
  1127.         END;
  1128.     END;
  1129.  
  1130. {--------------------------------------------------------------------------------------------------}
  1131. {$S GVRes}
  1132.  
  1133. PROCEDURE TGridView.DrawCell(aCell: GridCell;
  1134.                              aQDRect: Rect);
  1135.  
  1136.     BEGIN
  1137.     { Should always be overridden.}
  1138.  
  1139.     {$IFC qDebug}
  1140.     Writeln('TGridView: DrawCell MUST be overridden!');
  1141.     {$ENDC qDebug}
  1142.     END;
  1143.  
  1144. {--------------------------------------------------------------------------------------------------}
  1145. {$S GVNonRes}
  1146.  
  1147. PROCEDURE TGridView.DelColAt(aCol: INTEGER;
  1148.                              numOfCols: INTEGER);
  1149.  
  1150.     VAR
  1151.         aRect:                VRect;
  1152.  
  1153.     BEGIN
  1154.     IF (aCol < 1) | (numOfCols < 1) | (aCol + numOfCols - 1 > fNumOfCols) THEN
  1155.         BEGIN
  1156.         IF numOfCols <> 0 THEN
  1157.             BEGIN
  1158.             {$IFC qDebug AND qRangeCheck}
  1159.             Writeln('fNumOfCols = ', fNumOfCols: 1, '  aCol = ', aCol: 1);
  1160.             ProgramBreak('Range Check in DelColAt');
  1161.             EXIT(DelColAt);
  1162.             {$ENDC}
  1163.             END;
  1164.         END
  1165.     ELSE
  1166.         BEGIN
  1167.         ColToVRect(Max(1, aCol), Max(1, fNumOfCols - aCol + 1), aRect);
  1168.         fColWidths.DeleteItems(aCol, numOfCols);
  1169.         fNumOfCols := fNumOfCols - numOfCols;
  1170.         AdjustSize;
  1171.         InvalidVRect(aRect);
  1172.         END;
  1173.     END;
  1174.  
  1175. {--------------------------------------------------------------------------------------------------}
  1176. {$S GVNonRes}
  1177.  
  1178. PROCEDURE TGridView.DelRowAt(aRow: INTEGER;
  1179.                              numOfRows: INTEGER);
  1180.  
  1181.     VAR
  1182.         aRect:                VRect;
  1183.  
  1184.     BEGIN
  1185.     IF (aRow < 1) | (numOfRows < 1) | (aRow + numOfRows - 1 > fNumOfRows) THEN
  1186.         BEGIN
  1187.         IF numOfRows <> 0 THEN
  1188.             BEGIN
  1189.             {$IFC qDebug AND qRangeCheck}
  1190.             Writeln('fNumOfRows = ', fNumOfRows: 1, '  aRow = ', aRow: 1);
  1191.             ProgramBreak('Range Check in DelRowAt');
  1192.             EXIT(DelRowAt);
  1193.             {$ENDC}
  1194.             END;
  1195.         END
  1196.     ELSE
  1197.         BEGIN
  1198.         RowToVRect(Max(1, aRow), Max(1, fNumOfRows - aRow + 1), aRect);
  1199.         fRowHeights.DeleteItems(aRow, numOfRows);
  1200.         fNumOfRows := fNumOfRows - numOfRows;
  1201.         AdjustSize;
  1202.         InvalidVRect(aRect);
  1203.         END;
  1204.     END;
  1205.  
  1206. {--------------------------------------------------------------------------------------------------}
  1207. {$S GVNonRes}
  1208.  
  1209. PROCEDURE TGridView.DelColFirst(numOfCols: INTEGER);
  1210.  
  1211.     BEGIN
  1212.     DelColAt(1, numOfCols);
  1213.     END;
  1214.  
  1215. {--------------------------------------------------------------------------------------------------}
  1216. {$S GVNonRes}
  1217.  
  1218. PROCEDURE TGridView.DelRowFirst(numOfRows: INTEGER);
  1219.  
  1220.     BEGIN
  1221.     DelRowAt(1, numOfRows);
  1222.     END;
  1223.  
  1224. {--------------------------------------------------------------------------------------------------}
  1225. {$S GVNonRes}
  1226.  
  1227. PROCEDURE TGridView.DelColLast(numOfCols: INTEGER);
  1228.  
  1229.     BEGIN
  1230.     DelColAt(fNumOfCols - numOfCols + 1, numOfCols);
  1231.     END;
  1232.  
  1233. {--------------------------------------------------------------------------------------------------}
  1234. {$S GVNonRes}
  1235.  
  1236. PROCEDURE TGridView.DelRowLast(numOfRows: INTEGER);
  1237.  
  1238.     BEGIN
  1239.     DelRowAt(fNumOfRows - numOfRows + 1, numOfRows);
  1240.     END;
  1241.  
  1242. {--------------------------------------------------------------------------------------------------}
  1243. {$S GVRes}
  1244.  
  1245. PROCEDURE TGridView.EachCellDo(startCell, stopCell: GridCell;
  1246.                                PROCEDURE DoToCell(aCell: GridCell));
  1247.  
  1248.     VAR
  1249.         i, j:                INTEGER;
  1250.         firstRow:            INTEGER;
  1251.         lastRow:            INTEGER;
  1252.         firstCol:            INTEGER;
  1253.         lastCol:            INTEGER;
  1254.         aCell:                GridCell;
  1255.  
  1256.     BEGIN
  1257.     firstRow := Max(1, startCell.v);
  1258.     firstCol := Max(1, startCell.h);
  1259.     lastRow := Min(fNumOfRows, stopCell.v);
  1260.     lastCol := Min(fNumOfCols, stopCell.h);
  1261.  
  1262.     FOR j := firstRow TO lastRow DO
  1263.         BEGIN
  1264.         aCell.v := j;
  1265.         FOR i := firstCol TO lastCol DO
  1266.             BEGIN
  1267.             aCell.h := i;
  1268.             DoToCell(aCell);
  1269.             END;
  1270.         END;
  1271.     END;
  1272.  
  1273. {--------------------------------------------------------------------------------------------------}
  1274. {$S GVRes}
  1275.  
  1276. PROCEDURE TGridView.EachSelectedCellDo(PROCEDURE DoToCell(aCell: GridCell));
  1277.  
  1278.     BEGIN
  1279.     EachInRgn(fSelections, DoToCell);
  1280.     END;
  1281.  
  1282. {--------------------------------------------------------------------------------------------------}
  1283. {$S GVRes}
  1284.  
  1285. PROCEDURE TGridView.EachInRgn(aRgn: RgnHandle;
  1286.                               PROCEDURE DoToCell(aCell: GridCell));
  1287.  
  1288.     VAR
  1289.         row, col:            INTEGER;
  1290.         aCell:                GridCell;
  1291.         boundRect:            Rect;
  1292.  
  1293.     BEGIN
  1294.     boundRect := aRgn^^.rgnBBox;
  1295.     boundRect.right := boundRect.right - 1;
  1296.     boundRect.bottom := boundRect.bottom - 1;
  1297.     IF aRgn^^.rgnSize = 10 THEN                         { its a rectangle}
  1298.         EachCellDo(boundRect.topLeft, boundRect.botRight, DoToCell)
  1299.     ELSE
  1300.         FOR row := boundRect.top TO boundRect.bottom DO
  1301.             BEGIN
  1302.             aCell.v := row;
  1303.             FOR col := boundRect.left TO boundRect.right DO
  1304.                 BEGIN
  1305.                 aCell.h := col;
  1306.                 IF PtInRgn(aCell, aRgn) THEN
  1307.                     DoToCell(aCell);
  1308.                 END;
  1309.             END;
  1310.     END;
  1311.  
  1312. {--------------------------------------------------------------------------------------------------}
  1313. {$S GVRes}
  1314.  
  1315. FUNCTION TGridView.FirstSelectedCell: GridCell;
  1316.  
  1317.     VAR
  1318.         i, j:                INTEGER;
  1319.         bounds:             Rect;
  1320.         aCell:                GridCell;
  1321.  
  1322.     BEGIN
  1323.     IF EmptyRgn(fSelections) THEN
  1324.         FirstSelectedCell := gZeroPt
  1325.     ELSE
  1326.         BEGIN
  1327.         bounds := fSelections^^.rgnBBox;
  1328.         IF fSelections^^.rgnSize = 10 THEN                { whole rectangle }
  1329.             FirstSelectedCell := bounds.topLeft
  1330.         ELSE
  1331.             FOR i := bounds.top TO bounds.bottom - 1 DO
  1332.                 BEGIN
  1333.                 aCell.v := i;
  1334.                 FOR j := bounds.left TO bounds.right - 1 DO
  1335.                     BEGIN
  1336.                     aCell.h := j;
  1337.                     IF PtInRgn(aCell, fSelections) THEN
  1338.                         BEGIN
  1339.                         FirstSelectedCell := aCell;
  1340.                         EXIT(FirstSelectedCell);
  1341.                         END;
  1342.                     END;
  1343.                 END
  1344.         END;
  1345.     END;
  1346.  
  1347. {--------------------------------------------------------------------------------------------------}
  1348. {$S GVRes}
  1349.  
  1350. FUNCTION TGridView.GetColWidth(aCol: INTEGER): INTEGER;
  1351.  
  1352.     BEGIN
  1353.     IF (aCol < 1) | (aCol > fNumOfCols) THEN
  1354.         BEGIN
  1355.         {$IFC qRangeCheck AND qDebug}
  1356.         Writeln('fNumOfCols = ', fNumOfCols: 1, '  aCol = ', aCol: 1);
  1357.         ProgramBreak('Range Check in GetColWidth');
  1358.         {$ENDC}
  1359.         GetColWidth := 0;
  1360.         END
  1361.     ELSE
  1362.         GetColWidth := fColWidths.GetValue(aCol);
  1363.     END;
  1364.  
  1365. {--------------------------------------------------------------------------------------------------}
  1366. {$S GVRes}
  1367.  
  1368. FUNCTION TGridView.GetRowHeight(aRow: INTEGER): INTEGER;
  1369.  
  1370.     BEGIN
  1371.     IF (aRow < 1) | (aRow > fNumOfRows) THEN
  1372.         BEGIN
  1373.         {$IFC qRangeCheck AND qDebug}
  1374.         Writeln('fNumOfRows = ', fNumOfRows: 1, '  aRow = ', aRow: 1);
  1375.         ProgramBreak('Range Check in GetRowHeight');
  1376.         {$ENDC}
  1377.         GetRowHeight := 0;
  1378.         END
  1379.     ELSE
  1380.         GetRowHeight := fRowHeights.GetValue(aRow);
  1381.     END;
  1382.  
  1383. {--------------------------------------------------------------------------------------------------}
  1384. {$S GVRes}
  1385.  
  1386. PROCEDURE TGridView.InvalidateCell(aCell: GridCell);
  1387.  
  1388.     VAR
  1389.         aRect:                VRect;
  1390.  
  1391.     BEGIN
  1392.     CellToVRect(aCell, aRect);
  1393.     InvalidVRect(aRect);
  1394.     END;
  1395.  
  1396. {--------------------------------------------------------------------------------------------------}
  1397. {$S GVRes}
  1398.  
  1399. PROCEDURE TGridView.InvalidateSelection;
  1400.  
  1401.     BEGIN
  1402.     IF Focus THEN
  1403.         BEGIN
  1404.         CellsToPixels(fSelections, pInvalidateRgn);
  1405.         SectRgn(pInvalidateRgn, thePort^.clipRgn, pInvalidateRgn);
  1406.         InvalRgn(pInvalidateRgn);
  1407.         END;
  1408.     END;
  1409.  
  1410. {--------------------------------------------------------------------------------------------------}
  1411. {$S GVRes}
  1412.  
  1413. FUNCTION TGridView.IdentifyPoint(theQDPoint: Point;
  1414.                                  VAR aRow, aCol: INTEGER): GridViewPart;
  1415.  
  1416.     VAR
  1417.         aRect:                VRect;
  1418.         aPoint:             VPoint;
  1419.         aCell:                GridCell;
  1420.         aGridViewPart:        GridViewPart;
  1421.  
  1422.     BEGIN
  1423.     QDToViewPt(theQDPoint, aPoint);
  1424.     aCell := VPointToCell(aPoint);
  1425.     aRow := aCell.v;
  1426.     aCol := aCell.h;
  1427.  
  1428.     IF LONGINT(aCell) = 0 THEN
  1429.         aGridViewPart := badChoice
  1430.     ELSE
  1431.         BEGIN
  1432.         CellToVRect(aCell, aRect);
  1433.         InsetVRect(aRect, fColInset DIV 2, fRowInset DIV 2);
  1434.         aGridViewPart := inCell;
  1435.  
  1436.         IF fColInset > 0 THEN
  1437.             BEGIN
  1438.             IF (aPoint.h < aRect.left) THEN
  1439.                 BEGIN
  1440.                 aGridViewPart := inColumn;                { To the left of the cell }
  1441.                 END
  1442.  
  1443.             ELSE IF (aPoint.h >= aRect.right) THEN        { Remember PtInRgn will report a point as in
  1444.                                                          a region only if the pixel to the right
  1445.                                                          and below the point is contained in the
  1446.                                                          region. }
  1447.                 BEGIN
  1448.                 aGridViewPart := inColumn;                { To the right of the cell }
  1449.                 aCol := aCol + 1;
  1450.                 END;
  1451.             END;
  1452.  
  1453.         IF fRowInset > 0 THEN
  1454.             BEGIN
  1455.             IF (aPoint.v < aRect.top) THEN
  1456.                 BEGIN
  1457.                 IF (aGridViewPart = inColumn) THEN
  1458.                     aGridViewPart := inVertex            { Click on both }
  1459.                 ELSE
  1460.                     aGridViewPart := inRow;             { Above the cell }
  1461.                 END
  1462.  
  1463.             ELSE IF (aPoint.v >= aRect.bottom) THEN     { Remember PtInRgn will report a point as in
  1464.                                                          a region only if the pixel to the right
  1465.                                                          and below the point is contained in the
  1466.                                                          region. }
  1467.                 BEGIN
  1468.                 IF (aGridViewPart = inColumn) THEN
  1469.                     aGridViewPart := inVertex            { Click on both }
  1470.                 ELSE
  1471.                     aGridViewPart := inRow;             { Above the cell }
  1472.                 aRow := aRow + 1;
  1473.                 END;
  1474.             END;
  1475.         END;
  1476.     IdentifyPoint := aGridViewPart;
  1477.     END;
  1478.  
  1479. {--------------------------------------------------------------------------------------------------}
  1480. {$S GVRes}
  1481.  
  1482. PROCEDURE TGridView.InsColBefore(aCol: INTEGER;
  1483.                                  numOfCols: INTEGER;
  1484.                                  aWidth: INTEGER);
  1485.  
  1486.     VAR
  1487.         aRect:                VRect;
  1488.  
  1489.     BEGIN
  1490.     IF (aCol < 1) | (numOfCols < 1) THEN
  1491.         BEGIN
  1492.         IF numOfCols <> 0 THEN
  1493.             BEGIN
  1494.             {$IFC qDebug AND qRangeCheck}
  1495.             Writeln('fNumOfCols = ', fNumOfCols: 1, '  aCol = ', aCol: 1);
  1496.             ProgramBreak('Range Check in InsColBefore');
  1497.             {$ENDC}
  1498.             END;
  1499.         END
  1500.     ELSE
  1501.         BEGIN
  1502.         fColWidths.InsertItems(aCol, numOfCols, aWidth);
  1503.         fNumOfCols := fNumOfCols + numOfCols;
  1504.         AdjustSize;
  1505.         ColToVRect(Max(1, aCol), Max(1, fNumOfCols - aCol + 1), aRect);
  1506.         InvalidVRect(aRect);
  1507.         END;
  1508.     END;
  1509.  
  1510. {--------------------------------------------------------------------------------------------------}
  1511. {$S GVRes}
  1512.  
  1513. PROCEDURE TGridView.InsRowBefore(aRow: INTEGER;
  1514.                                  numOfRows: INTEGER;
  1515.                                  aHeight: INTEGER);
  1516.  
  1517.     VAR
  1518.         aRect:                VRect;
  1519.  
  1520.     BEGIN
  1521.     IF (aRow < 1) | (numOfRows < 1) THEN
  1522.         BEGIN
  1523.         IF numOfRows <> 0 THEN
  1524.             BEGIN
  1525.             {$IFC qDebug AND qRangeCheck}
  1526.             Writeln('fNumOfRows = ', fNumOfRows: 1, '  aRow = ', aRow: 1);
  1527.             ProgramBreak('Range Check in InsRowBefore');
  1528.             {$ENDC}
  1529.             END;
  1530.         END
  1531.     ELSE
  1532.         BEGIN
  1533.         fRowHeights.InsertItems(aRow, numOfRows, aHeight);
  1534.         fNumOfRows := fNumOfRows + numOfRows;
  1535.         AdjustSize;
  1536.         RowToVRect(Max(1, aRow), Max(1, fNumOfRows - aRow + 1), aRect);
  1537.         InvalidVRect(aRect);
  1538.         END;
  1539.     END;
  1540.  
  1541. {--------------------------------------------------------------------------------------------------}
  1542. {$S GVRes}
  1543.  
  1544. PROCEDURE TGridView.InsColLast(numOfCols: INTEGER;
  1545.                                aWidth: INTEGER);
  1546.  
  1547.     BEGIN
  1548.     InsColBefore(fNumOfCols + 1, numOfCols, aWidth);
  1549.     END;
  1550.  
  1551. {--------------------------------------------------------------------------------------------------}
  1552. {$S GVRes}
  1553.  
  1554. PROCEDURE TGridView.InsRowLast(numOfRows: INTEGER;
  1555.                                aHeight: INTEGER);
  1556.  
  1557.     BEGIN
  1558.     InsRowBefore(fNumOfRows + 1, numOfRows, aHeight);
  1559.     END;
  1560.  
  1561. {--------------------------------------------------------------------------------------------------}
  1562. {$S GVRes}
  1563.  
  1564. PROCEDURE TGridView.InsColFirst(numOfCols: INTEGER;
  1565.                                 aWidth: INTEGER);
  1566.  
  1567.     BEGIN
  1568.     InsColBefore(1, numOfCols, aWidth);
  1569.     END;
  1570.  
  1571. {--------------------------------------------------------------------------------------------------}
  1572. {$S GVRes}
  1573.  
  1574. PROCEDURE TGridView.InsRowFirst(numOfRows: INTEGER;
  1575.                                 aHeight: INTEGER);
  1576.  
  1577.     BEGIN
  1578.     InsRowBefore(1, numOfRows, aHeight);
  1579.     END;
  1580.  
  1581. {--------------------------------------------------------------------------------------------------}
  1582. {$S GVRes}
  1583.  
  1584. FUNCTION TGridView.IsCellSelected(aCell: GridCell): BOOLEAN;
  1585.  
  1586.     BEGIN
  1587.     IsCellSelected := PtInRgn(aCell, fSelections);
  1588.     END;
  1589.  
  1590. {--------------------------------------------------------------------------------------------------}
  1591. {$S GVRes}
  1592.  
  1593. FUNCTION TGridView.LastSelectedCell: GridCell;
  1594.  
  1595.     VAR
  1596.         i, j:                INTEGER;
  1597.         bounds:             Rect;
  1598.         aCell:                GridCell;
  1599.  
  1600.     BEGIN
  1601.     LastSelectedCell := gZeroPt;
  1602.     IF NOT EmptyRgn(fSelections) THEN
  1603.         BEGIN
  1604.         bounds := fSelections^^.rgnBBox;
  1605.         IF fSelections^^.rgnSize = 10 THEN                { whole rectangle }
  1606.             BEGIN
  1607.             aCell.h := bounds.right - 1;
  1608.             aCell.v := bounds.bottom - 1;
  1609.             LastSelectedCell := aCell;
  1610.             END
  1611.         ELSE
  1612.             FOR i := bounds.bottom - 1 DOWNTO bounds.top DO
  1613.                 BEGIN
  1614.                 aCell.v := i;
  1615.                 FOR j := bounds.right - 1 DOWNTO bounds.left DO
  1616.                     BEGIN
  1617.                     aCell.h := j;
  1618.                     IF PtInRgn(aCell, fSelections) THEN
  1619.                         BEGIN
  1620.                         LastSelectedCell := aCell;
  1621.                         EXIT(LastSelectedCell);
  1622.                         END;
  1623.                     END;
  1624.                 END
  1625.         END;
  1626.     END;
  1627.  
  1628. {--------------------------------------------------------------------------------------------------}
  1629. {$S GVRes}
  1630.  
  1631. PROCEDURE TGridView.RowToVRect(aRow: INTEGER;
  1632.                                numOfRows: INTEGER;
  1633.                                VAR aRect: VRect);
  1634.  
  1635.     VAR
  1636.         height:             LONGINT;
  1637.         topEdge:            LONGINT;
  1638.  
  1639.     BEGIN
  1640.     IF (aRow < 1) | (numOfRows < 1) | (aRow + numOfRows - 1 > fNumOfRows) THEN
  1641.         BEGIN
  1642.         {$IFC qDebug AND qRangeCheck}
  1643.         Writeln('fNumOfRows = ', fNumOfRows: 1, '  aRow = ', aRow: 1);
  1644.         ProgramBreak('Range Check in RowToVRect');
  1645.         {$ENDC}
  1646.         SetVRect(aRect, 0, 0, 0, 0);
  1647.         END
  1648.     ELSE                                                { all the params look OK }
  1649.         BEGIN
  1650.         IF fRowHeights.fNoOfChunks = 1 THEN             { only one row height }
  1651.             BEGIN
  1652.             height := fRowHeights.GetValue(1);
  1653.             topEdge := IntMultiply(height, aRow - 1);
  1654.             height := IntMultiply(height, numOfRows);
  1655.             END
  1656.         ELSE
  1657.             BEGIN
  1658.             topEdge := fRowHeights.SumValues(1, aRow - 1);
  1659.             height := fRowHeights.SumValues(aRow, numOfRows);
  1660.             END;
  1661.  
  1662.         SetVRect(aRect, 0, topEdge, fColWidths.fTotal, topEdge + height);
  1663.         END;
  1664.     END;
  1665.  
  1666. {--------------------------------------------------------------------------------------------------}
  1667. {$S GVRes}
  1668.  
  1669. PROCEDURE TGridView.ScrollSelectionIntoView(redraw: BOOLEAN);
  1670.  
  1671.     VAR
  1672.         botRightCell:        GridCell;
  1673.         topLeftRect, botRightRect, selectionRect: VRect;
  1674.         minToSee:            Point;
  1675.  
  1676.     BEGIN
  1677.     IF NOT (EmptyRgn(fSelections)) THEN
  1678.         BEGIN
  1679.         CellToVRect(fSelections^^.rgnBBox.topLeft, topLeftRect);
  1680.         SetPt(botRightCell, fSelections^^.rgnBBox.right - 1, fSelections^^.rgnBBox.bottom - 1);
  1681.         CellToVRect(botRightCell, botRightRect);
  1682.         UnionVRect(topLeftRect, botRightRect, selectionRect);
  1683.         minToSee.v := Max(topLeftRect.bottom - topLeftRect.top, botRightRect.bottom -
  1684.                           botRightRect.top);
  1685.         minToSee.h := Max(topLeftRect.right - topLeftRect.left, botRightRect.right -
  1686.                           botRightRect.left);
  1687.         RevealRect(selectionRect, minToSee, redraw);
  1688.         END;
  1689.     END;
  1690.  
  1691. {--------------------------------------------------------------------------------------------------}
  1692. {$S GVNonRes}
  1693.  
  1694. PROCEDURE TGridView.SetColWidth(aCol: INTEGER;
  1695.                                 numOfCols: INTEGER;
  1696.                                 aWidth: INTEGER);
  1697.  
  1698.     VAR
  1699.         aRect:                VRect;
  1700.  
  1701.     BEGIN
  1702.     {$IFC qRangeCheck AND qDebug}
  1703.     IF (aCol < 1) | (numOfCols < 1) | (aCol + numOfCols - 1 > fNumOfCols) THEN
  1704.         BEGIN
  1705.         Writeln('fNumOfCols = ', fNumOfCols: 1, '  aCol = ', aCol: 1);
  1706.         ProgramBreak('Range Check in SetColWidth');
  1707.         EXIT(SetColWidth);
  1708.         END;
  1709.     {$ENDC}
  1710.  
  1711.     IF (fColWidths.fNoOfChunks > 1) | (GetColWidth(1) <> aWidth) THEN
  1712.         BEGIN
  1713.         fColWidths.DeleteItems(aCol, numOfCols);
  1714.         fColWidths.InsertItems(aCol, numOfCols, aWidth);
  1715.         AdjustSize;
  1716.         ColToVRect(Max(1, aCol), Max(1, fNumOfCols - aCol + 1), aRect);
  1717.         InvalidVRect(aRect);
  1718.         END;
  1719.     END;
  1720.  
  1721. {--------------------------------------------------------------------------------------------------}
  1722. {$S GVNonRes}
  1723.  
  1724. PROCEDURE TGridView.SetRowHeight(aRow: INTEGER;
  1725.                                  numOfRows: INTEGER;
  1726.                                  aHeight: INTEGER);
  1727.  
  1728.     VAR
  1729.         aRect:                VRect;
  1730.  
  1731.     BEGIN
  1732.     {$IFC qRangeCheck AND qDebug}
  1733.     IF (aRow < 1) | (numOfRows < 1) | (aRow + numOfRows - 1 > fNumOfRows) THEN
  1734.         BEGIN
  1735.         Writeln('fNumOfRows = ', fNumOfRows: 1, '  aRow = ', aRow: 1);
  1736.         ProgramBreak('Range Check in SetRowHeight');
  1737.         EXIT(SetRowHeight);
  1738.         END;
  1739.     {$ENDC}
  1740.  
  1741.     IF NOT ((fRowHeights.fNoOfChunks = 1) & (GetRowHeight(1) = aHeight)) THEN
  1742.         BEGIN
  1743.         fRowHeights.DeleteItems(aRow, numOfRows);
  1744.         fRowHeights.InsertItems(aRow, numOfRows, aHeight);
  1745.         AdjustSize;
  1746.         RowToVRect(Max(1, aRow), Max(1, fNumOfRows - aRow + 1), aRect);
  1747.         InvalidVRect(aRect);
  1748.         END;
  1749.     END;
  1750.  
  1751. {--------------------------------------------------------------------------------------------------}
  1752. {$S GVRes}
  1753.  
  1754. PROCEDURE TGridView.SelectCell(theCell: GridCell;
  1755.                                extendSelection, highlight, select: BOOLEAN);
  1756.  
  1757.     BEGIN
  1758.     WITH theCell DO
  1759.         SetSelectionRect(h, v, h, v, extendSelection, highlight, select);
  1760.     END;
  1761.  
  1762. {--------------------------------------------------------------------------------------------------}
  1763. {$S GVRes}
  1764.  
  1765. PROCEDURE TGridView.SetEmptySelection(highlight: BOOLEAN);
  1766.  
  1767.     BEGIN
  1768.     SetEmptyRgn(fTempSelections);
  1769.     SetSelection(fTempSelections, kDontExtend, highlight, kSelect);
  1770.     END;
  1771.  
  1772. {--------------------------------------------------------------------------------------------------}
  1773. {$S GVRes}
  1774.  
  1775. PROCEDURE TGridView.SetSelection(cellsToSelect: RgnHandle;
  1776.                                  extendSelection, highlight, select: BOOLEAN);
  1777.  
  1778.     BEGIN
  1779.     {$IFC qDebug}
  1780.     WITH cellsToSelect^^.rgnBBox DO
  1781.         IF fSingleSelection & ((right - left > 1) | (bottom - top > 1)) THEN
  1782.             ProgramBreak('Attempt to select multiple cells when fSingleSelection is true');
  1783.     IF NOT EmptyRgn(cellsToSelect) THEN
  1784.         WITH cellsToSelect^^.rgnBBox DO
  1785.             IF (left < 1) | (top < 1) | (right > fNumOfCols + 1) | (bottom > fNumOfRows + 1) THEN
  1786.                 ProgramBreak('Attempted selection is outside the range of cells');
  1787.     {$ENDC}
  1788.  
  1789.     IF highlight THEN
  1790.         CopyRgn(fSelections, pPreviousSelection);        { save the old selection }
  1791.  
  1792.     {$IFC qDebug}
  1793.     UseTempRgn('TGridView.SetSelection');
  1794.     {$ENDC}
  1795.     SetRectRgn(gTempRgn, 1, 1, fNumOfCols + 1, fNumOfRows + 1);
  1796.     SectRgn(cellsToSelect, gTempRgn, gTempRgn);
  1797.  
  1798.     IF extendSelection & select THEN                    { extend the selection region }
  1799.         UnionRgn(gTempRgn, fSelections, fSelections)
  1800.     ELSE IF select THEN                                 { reset the selection region }
  1801.         CopyRgn(gTempRgn, fSelections)
  1802.     ELSE                                                { need to de-select the new region }
  1803.         DiffRgn(fSelections, gTempRgn, fSelections);
  1804.     {$IFC qDebug}
  1805.     DoneWithTempRgn;
  1806.     {$ENDC}
  1807.  
  1808.     CopyRgn(fSelections, fHLRegion);
  1809.  
  1810.     IF highlight THEN
  1811.         BEGIN
  1812.         { Turn the deselected cells off }
  1813.         DiffRgn(pPreviousSelection, fSelections, pDifference);
  1814.         HighlightCells(pDifference, fHLDesired, hlOFF);
  1815.  
  1816.         { Turn the newly selected cells on }
  1817.         DiffRgn(fSelections, pPreviousSelection, pDifference);
  1818.         HighlightCells(pDifference, hlOFF, fHLDesired);
  1819.         END;
  1820.     END;
  1821.  
  1822. {--------------------------------------------------------------------------------------------------}
  1823. {$S GVRes}
  1824.  
  1825. PROCEDURE TGridView.SetSelectionRect(left, top, right, bottom: INTEGER;
  1826.                                      extendSelection, highlight, select: BOOLEAN);
  1827.  
  1828.     BEGIN
  1829.     IF (left = 0) & (top = 0) & (right = 0) & (bottom = 0) THEN
  1830.         SetEmptyRgn(fTempSelections)
  1831.     ELSE
  1832.         SetRectRgn(fTempSelections, left, top, right + 1, bottom + 1);
  1833.     SetSelection(fTempSelections, extendSelection, highlight, select);
  1834.     END;
  1835.  
  1836. {--------------------------------------------------------------------------------------------------}
  1837. {$S GVNonRes}
  1838.  
  1839. PROCEDURE TGridView.SetSingleSelection(theSetting: BOOLEAN);
  1840.  
  1841.     BEGIN
  1842.     fSingleSelection := theSetting;
  1843.     END;
  1844.  
  1845. {--------------------------------------------------------------------------------------------------}
  1846. {$S GVRes}
  1847.  
  1848. FUNCTION TGridView.VPointToCell(aPoint: VPoint): GridCell;
  1849.  
  1850.     VAR
  1851.         aCell:                GridCell;
  1852.  
  1853.     BEGIN
  1854.     aCell.h := fColWidths.FindItem(aPoint.h);
  1855.     aCell.v := fRowHeights.FindItem(aPoint.v);
  1856.     IF (aCell.h = 0) | (aCell.v = 0) THEN
  1857.         VPointToCell := gZeroPt
  1858.     ELSE
  1859.         VPointToCell := aCell;
  1860.     END;
  1861.  
  1862. {--------------------------------------------------------------------------------------------------}
  1863. {$S GVRes}
  1864.  
  1865. FUNCTION TGridView.VPointToLastCell(aPoint: VPoint): GridCell;
  1866.  
  1867.     VAR
  1868.         aCell:                GridCell;
  1869.  
  1870.     BEGIN
  1871.     aCell.h := fColWidths.FindItem(aPoint.h);
  1872.     IF aCell.h = 0 THEN                                 { If its invalid, return the last column }
  1873.         aCell.h := fNumOfCols;
  1874.  
  1875.     aCell.v := fRowHeights.FindItem(aPoint.v);
  1876.     IF aCell.v = 0 THEN                                 { If its invalid, return the last row }
  1877.         aCell.v := fNumOfRows;
  1878.  
  1879.     VPointToLastCell := aCell;
  1880.     END;
  1881.  
  1882. {--------------------------------------------------------------------------------------------------}
  1883. {$S GVFields}
  1884.  
  1885. PROCEDURE TGridView.Fields(PROCEDURE DoToField(fieldName: Str255;
  1886.                                                fieldAddr: Ptr;
  1887.                                                fieldType: INTEGER)); OVERRIDE;
  1888.  
  1889.     BEGIN
  1890.     DoToField('TGridView', NIL, bClass);
  1891.     DoToField('fSelections', @fSelections, bRgnHandle);
  1892.     DoToField('fHLRegion', @fHLRegion, bRgnHandle);
  1893.     DoToField('fTempSelections', @fTempSelections, bRgnHandle);
  1894.     DoToField('fNumOfRows', @fNumOfRows, bInteger);
  1895.     DoToField('fRowHeights', @fRowHeights, bObject);
  1896.     DoToField('fNumOfCols', @fNumOfCols, bInteger);
  1897.     DoToField('fColWidths', @fColWidths, bObject);
  1898.     DoToField('fRowInset', @fRowInset, bInteger);
  1899.     DoToField('fColInset', @fColInset, bInteger);
  1900.     DoToField('fAdornRows', @fAdornRows, bBoolean);
  1901.     DoToField('fAdornCols', @fAdornCols, bBoolean);
  1902.     DoToField('fSingleSelection', @fSingleSelection, bBoolean);
  1903.  
  1904.     INHERITED Fields(DoToField);
  1905.     END;
  1906.  
  1907. {--------------------------------------------------------------------------------------------------}
  1908. {$S GVOpen}
  1909.  
  1910. PROCEDURE TTextGridView.ITextGridView(itsDocument: TDocument; { Its document }
  1911.                                       itsSuperView: TView; { Its parent view }
  1912.                                       itsLocation: VPoint; { Top, Left in parent's coords }
  1913.                                       itsSize: VPoint;
  1914.                                       itsHSizeDet, itsVSizeDet: SizeDeterminer; { Size determiners }
  1915.                                       numOfRows: INTEGER; { Number of rows initially }
  1916.                                       numOfCols: INTEGER; { Number of columns initially }
  1917.                                       rowHeight: INTEGER; { Row height, or zero for font height }
  1918.                                       colWidth: INTEGER; { Width of items in the columns }
  1919.                                       adornRows: BOOLEAN; { Adornment for Rows? }
  1920.                                       adornCols: BOOLEAN; { Adornment for Columns? }
  1921.                                       rowInset: INTEGER; { horizontal space between cells }
  1922.                                       colInset: INTEGER; { vertical space between cells }
  1923.                                       singleSelection: BOOLEAN; { single cell selection? }
  1924.                                       itsTextStyle: TextStyle); { size, color, etc. font info }
  1925.  
  1926.     BEGIN
  1927.     fTextStyle := itsTextStyle;
  1928.  
  1929.     SetUpFont;
  1930.     IF rowHeight = 0 THEN
  1931.         rowHeight := fLineHeight + rowInset;
  1932.  
  1933.     IGridView(itsDocument, itsSuperView, itsLocation, itsSize, itsHSizeDet, itsVSizeDet, numOfRows,
  1934.               numOfCols, rowHeight, colWidth, adornRows, adornCols, rowInset, colInset,
  1935.               singleSelection);
  1936.  
  1937.     IF (fNumOfCols = 1) & (fSizeDeterminer[h] <> sizeFixed) & (GetColWidth(1) = 0) & (fSuperView <>
  1938.        NIL) THEN
  1939.         SetColWidth(1, fNumOfCols, fSuperView.fSize.h);
  1940.     END;
  1941.  
  1942. {--------------------------------------------------------------------------------------------------}
  1943. {$S GVOpen}
  1944.  
  1945. PROCEDURE TTextGridView.IRes(itsDocument: TDocument;
  1946.                              itsSuperView: TView;
  1947.                              VAR itsParams: Ptr); OVERRIDE;
  1948.  
  1949.     VAR
  1950.         itsTextStyle:        TextStyle;
  1951.  
  1952.     BEGIN
  1953.     { The ancestor will need to focus when adding rows or columns.
  1954.     Get the information necessary to focus since this class sets textStyle when focusing }
  1955.     fTextStyle := gSystemStyle;                         { Put in safe state }
  1956.  
  1957.     INHERITED IRes(itsDocument, itsSuperView, itsParams);
  1958.  
  1959.     WITH TextGridViewTemplatePtr(itsParams)^ DO
  1960.         BEGIN
  1961.         SetTextStyle(itsTextStyle, GetFontNum(itsFontName), itsFontFace, itsFontSize, itsFontColor);
  1962.         fTextStyle := itsTextStyle;
  1963.         END;
  1964.  
  1965.     SetUpFont;
  1966.  
  1967.     IF fNumOfRows > 0 THEN
  1968.         IF GetRowHeight(1) = 0 THEN                     { set row height from font }
  1969.             SetRowHeight(1, fNumOfRows, fLineHeight + fRowInset);
  1970.  
  1971.     IF (fNumOfCols = 1) & (fSizeDeterminer[h] <> sizeFixed) & (GetColWidth(1) = 0) THEN
  1972.         SetColWidth(1, fNumOfCols, fSize.h);
  1973.  
  1974.     OffsetPtrWStr(itsParams, SIZEOF(TextGridViewTemplate));
  1975.     END;
  1976.  
  1977. {--------------------------------------------------------------------------------------------------}
  1978. {$S GVNonRes}
  1979.  
  1980. PROCEDURE TTextGridView.WRes(theResource: ViewRsrcHndl;
  1981.                              VAR itsParams: Ptr); OVERRIDE;
  1982.  
  1983.     VAR
  1984.         theSize:            INTEGER;
  1985.         theFont:            Str255;
  1986.         tgPtr:                TextGridViewTemplatePtr;
  1987.  
  1988.     BEGIN
  1989.     INHERITED WRes(theResource, itsParams);
  1990.  
  1991.     theSize := fTextStyle.tsSize;
  1992.     GetPortFontInfo(fTextStyle.tsFont, theFont, theSize);
  1993.  
  1994.     tgPtr := TextGridViewTemplatePtr(ExpandPtrWStr(theResource, itsParams,
  1995.                                                    SIZEOF(TextGridViewTemplate), LENGTH(theFont)));
  1996.  
  1997.     WITH tgPtr^, fTextStyle DO
  1998.         BEGIN
  1999.         itsFontFace := tsFace;
  2000.         itsFontSize := theSize;
  2001.         itsFontColor := tsColor;
  2002.         { itsFontName := theFont; }
  2003.         END;
  2004.     CopyStr255(theFont, PRStr(tgPtr^.itsFontName));
  2005.     END;
  2006.  
  2007. {--------------------------------------------------------------------------------------------------}
  2008. {$S GVNonRes}
  2009.  
  2010. PROCEDURE TTextGridView.WriteRes(theResource: ViewRsrcHndl;
  2011.                                  VAR itsParams: Ptr); OVERRIDE;
  2012.  
  2013.     BEGIN
  2014.     gWResSignature := 'txtg'; gWResType := 'TTextGridView';
  2015.     WRes(theResource, itsParams);
  2016.     END;
  2017.  
  2018. {--------------------------------------------------------------------------------------------------}
  2019. {$S GVRes}
  2020.  
  2021. PROCEDURE TTextGridView.DrawCell(aCell: GridCell;
  2022.                                  aQDRect: Rect); OVERRIDE;
  2023.  
  2024.     VAR
  2025.         theText:            Str255;
  2026.  
  2027.     BEGIN
  2028.     GetText(aCell, theText);
  2029.  
  2030.     IF (GetColWidth(aCell.h) > 0) THEN
  2031.         MADrawString(@theText, aQDRect, teJustSystem);
  2032.     END;
  2033.  
  2034. {--------------------------------------------------------------------------------------------------}
  2035. {$S GVRes}
  2036.  
  2037. FUNCTION TTextGridView.Focus: BOOLEAN; OVERRIDE;
  2038.  
  2039.     BEGIN
  2040.     IF INHERITED Focus THEN
  2041.         BEGIN
  2042.         SetPen;
  2043.         Focus := TRUE;
  2044.         END
  2045.     ELSE
  2046.         Focus := FALSE;
  2047.     END;
  2048.  
  2049. {--------------------------------------------------------------------------------------------------}
  2050. {$S GVOpen}
  2051.  
  2052. PROCEDURE TTextGridView.SetUpFont;
  2053.  
  2054.     VAR
  2055.         savedPort:            GrafPtr;
  2056.         theFontInfo:        FontInfo;
  2057.  
  2058.     BEGIN
  2059.     GetPort(savedPort);
  2060.     SetPort(gWorkPort);
  2061.  
  2062.     SetPen;
  2063.     GetFontInfo(theFontInfo);
  2064.  
  2065.     SetPort(savedPort);
  2066.  
  2067.     WITH theFontInfo DO
  2068.         BEGIN
  2069.         fLineHeight := ascent + descent + leading;
  2070.         fLineAscent := ascent + (leading DIV 2);
  2071.         END;
  2072.  
  2073.     END;
  2074.  
  2075. {--------------------------------------------------------------------------------------------------}
  2076. {$S GVRes}
  2077.  
  2078. PROCEDURE TTextGridView.SetPen;
  2079.  
  2080.     VAR
  2081.         itsTextStyle:        TextStyle;
  2082.  
  2083.     BEGIN
  2084.     itsTextStyle := fTextStyle;
  2085.     SetPortTextStyle(itsTextStyle);
  2086.     PenNormal;
  2087.     END;
  2088.  
  2089. {--------------------------------------------------------------------------------------------------}
  2090. {$S GVRes}
  2091.  
  2092. PROCEDURE TTextGridView.GetText(aCell: GridCell;
  2093.                                 VAR aString: Str255);
  2094.  
  2095.     BEGIN
  2096.     { MUST be overridden! }
  2097.  
  2098.     {$IFC qDebug}
  2099.     Writeln('TTextGridView: GetText MUST be OVERRIDDEN!');
  2100.     {$ENDC qDebug}
  2101.     END;
  2102.  
  2103. {--------------------------------------------------------------------------------------------------}
  2104. {$S GVFields}
  2105.  
  2106. PROCEDURE TTextGridView.Fields(PROCEDURE DoToField(fieldName: Str255;
  2107.                                                    fieldAddr: Ptr;
  2108.                                                    fieldType: INTEGER)); OVERRIDE;
  2109.  
  2110.     BEGIN
  2111.     DoToField('TTextGridView', NIL, bClass);
  2112.     DoToField('fLineHeight', @fLineHeight, bInteger);
  2113.     DoToField('fLineAscent', @fLineAscent, bInteger);
  2114.     {$Push} {$H-}
  2115.     TextStyleFields('fTextStyle', fTextStyle, DoToField);
  2116.     {$Pop}
  2117.  
  2118.     INHERITED Fields(DoToField);
  2119.     END;
  2120.  
  2121. {--------------------------------------------------------------------------------------------------}
  2122. {$S GVOpen}
  2123.  
  2124. PROCEDURE TTextListView.ITextListView(itsDocument: TDocument; { Its document }
  2125.                                       itsSuperView: TView; { Its parent view }
  2126.                                       itsLocation: VPoint; { Top, Left in parent's coords }
  2127.                                       itsSize: VPoint;
  2128.                                       itsHSizeDet, itsVSizeDet: SizeDeterminer; { Size determiners }
  2129.                                       numOfItems: INTEGER; { Number of items initially }
  2130.                                       rowHeight: INTEGER; { Row height, or zero for font height }
  2131.                                       colWidth: INTEGER; { Width of items in the columns }
  2132.                                       adornRows: BOOLEAN; { Draw the row adornments? }
  2133.                                       adornCols: BOOLEAN; { Draw the col adornment? }
  2134.                                       rowInset: INTEGER; { Amount to inset the rows }
  2135.                                       colInset: INTEGER; { Amount to inset the column }
  2136.                                       singleSelection: BOOLEAN; { single cell selection? }
  2137.                                       itsTextStyle: TextStyle); { size, color, etc. font info }
  2138.  
  2139.     BEGIN
  2140.     ITextGridView(itsDocument, itsSuperView, itsLocation, itsSize, itsHSizeDet, itsVSizeDet,
  2141.                   numOfItems, 1, rowHeight, colWidth, adornRows, adornCols, rowInset, colInset,
  2142.                   singleSelection, itsTextStyle);
  2143.     END;
  2144.  
  2145. {--------------------------------------------------------------------------------------------------}
  2146. {$S GVNonRes}
  2147.  
  2148. PROCEDURE TTextListView.WriteRes(theResource: ViewRsrcHndl;
  2149.                                  VAR itsParams: Ptr); OVERRIDE;
  2150.  
  2151.     BEGIN
  2152.     gWResSignature := 'lstg'; gWResType := 'TTextListView';
  2153.     WRes(theResource, itsParams);
  2154.     END;
  2155.  
  2156. {--------------------------------------------------------------------------------------------------}
  2157. {$S GVRes}
  2158.  
  2159. PROCEDURE TTextListView.AllItemsDo(PROCEDURE DoToItem(anItem: INTEGER));
  2160.  
  2161.     BEGIN
  2162.     EachItemDo(1, fNumOfRows, DoToItem);
  2163.     END;
  2164.  
  2165. {--------------------------------------------------------------------------------------------------}
  2166. {$S GVRes}
  2167.  
  2168. FUNCTION TTextListView.CanSelectCell(aCell: GridCell): BOOLEAN; OVERRIDE;
  2169.  
  2170.     BEGIN
  2171.     CanSelectCell := INHERITED CanSelectCell(aCell) & CanSelectItem(aCell.v);
  2172.     END;
  2173.  
  2174. {--------------------------------------------------------------------------------------------------}
  2175. {$S GVRes}
  2176.  
  2177. FUNCTION TTextListView.CanSelectItem(anItem: INTEGER): BOOLEAN;
  2178.  
  2179.     BEGIN
  2180.     CanSelectItem := (anItem >= 1) & (anItem <= fNumOfRows);
  2181.     END;
  2182.  
  2183. {--------------------------------------------------------------------------------------------------}
  2184. {$S GVNonRes}
  2185.  
  2186. PROCEDURE TTextListView.DelItemAt(anItem: INTEGER;
  2187.                                   numOfItems: INTEGER);
  2188.  
  2189.     BEGIN
  2190.     DelRowAt(anItem, numOfItems);
  2191.     END;
  2192.  
  2193. {--------------------------------------------------------------------------------------------------}
  2194. {$S GVNonRes}
  2195.  
  2196. PROCEDURE TTextListView.DelItemFirst(numOfItems: INTEGER);
  2197.  
  2198.     BEGIN
  2199.     DelItemAt(1, numOfItems);
  2200.     END;
  2201.  
  2202. {--------------------------------------------------------------------------------------------------}
  2203. {$S GVNonRes}
  2204.  
  2205. PROCEDURE TTextListView.DelItemLast(numOfItems: INTEGER);
  2206.  
  2207.     BEGIN
  2208.     DelItemAt(fNumOfRows - numOfItems + 1, numOfItems);
  2209.     END;
  2210.  
  2211. {--------------------------------------------------------------------------------------------------}
  2212. {$S GVRes}
  2213.  
  2214. PROCEDURE TTextListView.EachItemDo(start, stop: INTEGER;
  2215.                                    PROCEDURE DoToItem(anItem: INTEGER));
  2216.  
  2217.     VAR
  2218.         i:                    INTEGER;
  2219.  
  2220.     BEGIN
  2221.     FOR i := start TO stop DO
  2222.         DoToItem(i);
  2223.     END;
  2224.  
  2225. {--------------------------------------------------------------------------------------------------}
  2226. {$S GVRes}
  2227.  
  2228. PROCEDURE TTextListView.EachSelectedItemDo(PROCEDURE
  2229.                                            DoToItem(anItem: INTEGER));
  2230.  
  2231.     PROCEDURE DoToCell(aCell: GridCell);
  2232.  
  2233.         BEGIN
  2234.         DoToItem(aCell.v);
  2235.         END;
  2236.  
  2237.     BEGIN
  2238.     EachInRgn(fSelections, DoToCell);
  2239.     END;
  2240.  
  2241. {--------------------------------------------------------------------------------------------------}
  2242. {$S GVRes}
  2243.  
  2244. FUNCTION TTextListView.FirstSelectedItem: INTEGER;
  2245.  
  2246.     VAR
  2247.         aGridCell:            GridCell;
  2248.  
  2249.     BEGIN
  2250.     aGridCell := FirstSelectedCell;
  2251.     FirstSelectedItem := aGridCell.v;
  2252.     END;
  2253.  
  2254. {--------------------------------------------------------------------------------------------------}
  2255. {$S GVRes}
  2256.  
  2257. FUNCTION TTextListView.GetItemHeight(anItem: INTEGER): INTEGER;
  2258.  
  2259.     BEGIN
  2260.     GetItemHeight := GetRowHeight(anItem);
  2261.     END;
  2262.  
  2263. {--------------------------------------------------------------------------------------------------}
  2264. {$S GVRes}
  2265.  
  2266. FUNCTION TTextListView.GetItemWidth: INTEGER;
  2267.  
  2268.     BEGIN
  2269.     GetItemWidth := GetColWidth(1);
  2270.     END;
  2271.  
  2272. {--------------------------------------------------------------------------------------------------}
  2273. {$S GVRes}
  2274.  
  2275. PROCEDURE TTextListView.GetItemText(anItem: INTEGER;
  2276.                                     VAR aString: Str255);
  2277.  
  2278.     BEGIN
  2279.     { MUST be overridden !!! }
  2280.  
  2281.     {$IFC qDebug}
  2282.     Writeln('TTextListView: GetItemText MUST be OVERRIDDEN!');
  2283.     {$ENDC qDebug}
  2284.  
  2285.     END;
  2286.  
  2287. {--------------------------------------------------------------------------------------------------}
  2288. {$S GVRes}
  2289.  
  2290. PROCEDURE TTextListView.GetText(aCell: GridCell;
  2291.                                 VAR aString: Str255); OVERRIDE;
  2292.  
  2293.     BEGIN
  2294.     GetItemText(aCell.v, aString);
  2295.     END;
  2296.  
  2297. {--------------------------------------------------------------------------------------------------}
  2298. {$S GVRes}
  2299.  
  2300. PROCEDURE TTextListView.InsItemBefore(anItem: INTEGER;
  2301.                                       numOfItems: INTEGER);
  2302.  
  2303.     BEGIN
  2304.     InsRowBefore(anItem, numOfItems, fLineHeight + fRowInset);
  2305.     END;
  2306.  
  2307. {--------------------------------------------------------------------------------------------------}
  2308. {$S GVRes}
  2309.  
  2310. PROCEDURE TTextListView.InsItemFirst(numOfItems: INTEGER);
  2311.  
  2312.     BEGIN
  2313.     InsItemBefore(1, numOfItems);
  2314.     END;
  2315.  
  2316. {--------------------------------------------------------------------------------------------------}
  2317. {$S GVRes}
  2318.  
  2319. PROCEDURE TTextListView.InsItemLast(numOfItems: INTEGER);
  2320.  
  2321.     BEGIN
  2322.     InsItemBefore(fNumOfRows + 1, numOfItems);
  2323.     END;
  2324.  
  2325. {--------------------------------------------------------------------------------------------------}
  2326. {$S GVRes}
  2327.  
  2328. PROCEDURE TTextListView.InvalidateItem(anItem: INTEGER);
  2329.  
  2330.     VAR
  2331.         aCell:                GridCell;
  2332.  
  2333.     BEGIN
  2334.     aCell.h := 1;
  2335.     aCell.v := anItem;
  2336.     InvalidateCell(aCell);
  2337.     END;
  2338.  
  2339. {--------------------------------------------------------------------------------------------------}
  2340. {$S GVRes}
  2341.  
  2342. FUNCTION TTextListView.IsItemSelected(anItem: INTEGER): BOOLEAN;
  2343.  
  2344.     VAR
  2345.         aCell:                GridCell;
  2346.  
  2347.     BEGIN
  2348.     aCell.h := 1;
  2349.     aCell.v := anItem;
  2350.     IsItemSelected := IsCellSelected(aCell);
  2351.     END;
  2352.  
  2353. {--------------------------------------------------------------------------------------------------}
  2354. {$S GVRes}
  2355.  
  2356. FUNCTION TTextListView.LastSelectedItem: INTEGER;
  2357.  
  2358.     VAR
  2359.         aGridCell:            GridCell;
  2360.  
  2361.     BEGIN
  2362.     aGridCell := LastSelectedCell;
  2363.     LastSelectedItem := aGridCell.v;
  2364.     END;
  2365.  
  2366. {--------------------------------------------------------------------------------------------------}
  2367. {$S GVNonRes}
  2368.  
  2369. PROCEDURE TTextListView.Resize(width, height: VCoordinate;
  2370.                                invalidate: BOOLEAN); OVERRIDE;
  2371.  
  2372.     BEGIN
  2373.     INHERITED Resize(width, height, invalidate);
  2374.     IF fNumOfCols = 1 THEN
  2375.         BEGIN
  2376.         fColWidths.fTotal := fColWidths.fTotal - fColWidths.fChunks^^[0].value + width;
  2377.         fColWidths.fChunks^^[0].value := width;
  2378.         END;
  2379.     END;
  2380.  
  2381. {--------------------------------------------------------------------------------------------------}
  2382. {$S GVRes}
  2383.  
  2384. PROCEDURE TTextListView.SelectCell(theCell: GridCell;
  2385.                                    extendSelection, highlight, select: BOOLEAN); OVERRIDE;
  2386.  
  2387.     BEGIN
  2388.     SelectItem(theCell.v, extendSelection, highlight, select);
  2389.     END;
  2390.  
  2391. {--------------------------------------------------------------------------------------------------}
  2392. {$S GVRes}
  2393.  
  2394. PROCEDURE TTextListView.SelectItem(anItem: INTEGER;
  2395.                                    extendSelection, highlight, select: BOOLEAN);
  2396.  
  2397.     VAR
  2398.         aCell:                GridCell;
  2399.  
  2400.     BEGIN
  2401.     aCell.v := anItem;
  2402.     aCell.h := Min(1, anItem);
  2403.  
  2404.     INHERITED SelectCell(aCell, extendSelection, highlight, select);
  2405.     END;
  2406.  
  2407. {--------------------------------------------------------------------------------------------------}
  2408. {$S GVNonRes}
  2409.  
  2410. PROCEDURE TTextListView.SetItemHeight(anItem: INTEGER;
  2411.                                       numOfItems: INTEGER;
  2412.                                       aHeight: INTEGER);
  2413.  
  2414.     BEGIN
  2415.     SetRowHeight(anItem, numOfItems, aHeight);
  2416.     END;
  2417.  
  2418. {--------------------------------------------------------------------------------------------------}
  2419. {$S GVNonRes}
  2420.  
  2421. PROCEDURE TTextListView.SetItemWidth(aWidth: INTEGER);
  2422.  
  2423.     BEGIN
  2424.     SetColWidth(1, 1, aWidth);
  2425.     END;
  2426.  
  2427. {--------------------------------------------------------------------------------------------------}
  2428. {$S GVFields}
  2429.  
  2430. PROCEDURE TTextListView.Fields(PROCEDURE DoToField(fieldName: Str255;
  2431.                                                    fieldAddr: Ptr;
  2432.                                                    fieldType: INTEGER)); OVERRIDE;
  2433.  
  2434.     BEGIN
  2435.     DoToField('TTextListView', NIL, bClass);
  2436.     INHERITED Fields(DoToField);
  2437.     END;
  2438.  
  2439. {--------------------------------------------------------------------------------------------------}
  2440. {$S GVSelCommand}
  2441.  
  2442. PROCEDURE TCellSelectCommand.ICellSelectCommand(itsView: TGridView;
  2443.                                                 theShiftKey, theCmdKey: BOOLEAN);
  2444.  
  2445.     VAR
  2446.         fi:                 FailInfo;
  2447.  
  2448.     PROCEDURE HandleFailure(error: OSErr;
  2449.                             message: LONGINT);
  2450.  
  2451.         BEGIN
  2452.         Free;
  2453.         END;
  2454.  
  2455.     BEGIN
  2456.     fThisSelection := NIL;
  2457.     fPrevSelection := NIL;
  2458.     fDifference := NIL;
  2459.     fGridView := NIL;
  2460.  
  2461.     fShiftKey := theShiftKey;
  2462.     fCmdKey := theCmdKey;
  2463.  
  2464.     ICommand(cNoCommand, NIL, itsView, itsView.GetScroller(FALSE));
  2465.     fCanUndo := FALSE;
  2466.     fCausesChange := FALSE;
  2467.     fViewConstrain := FALSE;
  2468.  
  2469.     fGridView := itsView;
  2470.  
  2471.     fAnchorCell := gZeroPt;                             { At least set it to something }
  2472.     fPrevCell.h := - 1;                                 { ??? Blech! there must be a better way }
  2473.     fPrevCell.v := - 1;                                 { ??? Blech! there must be a better way }
  2474.  
  2475.     CatchFailures(fi, HandleFailure);
  2476.     fPrevSelection := MakeNewRgn;
  2477.     CopyRgn(fGridView.fSelections, fPrevSelection);
  2478.     fThisSelection := fGridView.fHLRegion;
  2479.     SetEmptyRgn(fThisSelection);
  2480.     fDifference := MakeNewRgn;
  2481.     Success(fi);
  2482.     END;
  2483.  
  2484. {--------------------------------------------------------------------------------------------------}
  2485. {$S GVDoCommand}
  2486.  
  2487. PROCEDURE TCellSelectCommand.Free; OVERRIDE;
  2488.  
  2489.     BEGIN
  2490.     IF fPrevSelection <> NIL THEN
  2491.         DisposeRgn(fPrevSelection);
  2492.     fPrevSelection := NIL;
  2493.  
  2494.     IF fDifference <> NIL THEN
  2495.         DisposeRgn(fDifference);
  2496.     fDifference := NIL;
  2497.  
  2498.     fThisSelection := NIL;                                { I don't own it so I don't dispose it. But,
  2499.                                                          I sure don't need a reference to it any
  2500.                                                          more. }
  2501.  
  2502.     INHERITED Free;
  2503.     END;
  2504.  
  2505. {--------------------------------------------------------------------------------------------------}
  2506. {$S GVDoCommand}
  2507.  
  2508. PROCEDURE TCellSelectCommand.ComputeAnchorCell(VAR clickedCell: GridCell);
  2509.  
  2510.     BEGIN
  2511.     fAnchorCell := clickedCell;
  2512.  
  2513.     IF fShiftKey & (NOT EmptyRgn(fPrevSelection)) THEN
  2514.         WITH fPrevSelection^^.rgnBBox DO
  2515.             BEGIN
  2516.             IF fAnchorCell.h >= left THEN
  2517.                 fAnchorCell.h := left
  2518.             ELSE
  2519.                 fAnchorCell.h := right - 1;
  2520.             IF fAnchorCell.v >= top THEN
  2521.                 fAnchorCell.v := top
  2522.             ELSE
  2523.                 fAnchorCell.v := bottom - 1;
  2524.             END;
  2525.     END;
  2526.  
  2527. {--------------------------------------------------------------------------------------------------}
  2528. {$S GVDoCommand}
  2529.  
  2530. PROCEDURE TCellSelectCommand.ComputeNewSelection(VAR clickedCell: GridCell);
  2531.  
  2532.     VAR
  2533.         r:                    Rect;
  2534.  
  2535.     BEGIN
  2536.     IF fGridView.CanSelectCell(clickedCell) THEN
  2537.         BEGIN
  2538.         IF fGridView.fSingleSelection | (NOT fShiftKey) THEN
  2539.             SetRect(r, clickedCell.h, clickedCell.v, clickedCell.h + 1, clickedCell.v + 1)
  2540.         ELSE
  2541.             BEGIN
  2542.             Pt2Rect(fAnchorCell, clickedCell, r);
  2543.             r.right := r.right + 1;
  2544.             r.bottom := r.bottom + 1;
  2545.             END;
  2546.         RectRgn(fThisSelection, r);
  2547.         IF fCmdKey & (NOT fGridView.fSingleSelection) THEN
  2548.             IF fDeselecting THEN
  2549.                 DiffRgn(fPrevSelection, fThisSelection, fThisSelection)
  2550.             ELSE
  2551.                 UnionRgn(fPrevSelection, fThisSelection, fThisSelection);
  2552.         END;
  2553.     END;
  2554.  
  2555. {--------------------------------------------------------------------------------------------------}
  2556. {$S GVDoCommand}
  2557.  
  2558. PROCEDURE TCellSelectCommand.HighlightNewSelection;
  2559.  
  2560.     BEGIN
  2561.     { Turn off previously selected cells }
  2562.     DiffRgn(fPrevSelection, fThisSelection, fDifference);
  2563.     fGridView.HighlightCells(fDifference, fGridView.fHLDesired, hlOFF);
  2564.  
  2565.     { Turn on newly selected cells}
  2566.     DiffRgn(fThisSelection, fPrevSelection, fDifference);
  2567.     fGridView.HighlightCells(fDifference, hlOFF, fGridView.fHLDesired);
  2568.     END;
  2569.  
  2570. {--------------------------------------------------------------------------------------------------}
  2571. {$S GVDoCommand}
  2572.  
  2573. PROCEDURE TCellSelectCommand.TrackFeedback(anchorPoint, nextPoint: VPoint;
  2574.                                            turnItOn, mouseDidMove: BOOLEAN); OVERRIDE;
  2575.  
  2576.     BEGIN
  2577.     END;
  2578.  
  2579. {--------------------------------------------------------------------------------------------------}
  2580. {$S GVDoCommand}
  2581.  
  2582. FUNCTION TCellSelectCommand.TrackMouse(aTrackPhase: TrackPhase;
  2583.                                        VAR anchorPoint, previousPoint, nextPoint: VPoint;
  2584.                                        mouseDidMove: BOOLEAN): TCommand; OVERRIDE;
  2585.  
  2586.     VAR
  2587.         clickedCell:        GridCell;
  2588.         viewExtent:         VRect;
  2589.         clippedPoint:        VPoint;
  2590.  
  2591.     BEGIN
  2592.     IF mouseDidMove THEN
  2593.         BEGIN
  2594.         fGridView.GetExtent(viewExtent);
  2595.         clippedPoint := nextPoint;
  2596.         PinVRect(viewExtent, clippedPoint);
  2597.         clickedCell := fGridView.VPointToCell(clippedPoint);
  2598.         IF aTrackPhase = TrackPress THEN
  2599.             BEGIN
  2600.             ComputeAnchorCell(clickedCell);
  2601.             IF fCmdKey THEN
  2602.                 fDeselecting := PtInRgn(fAnchorCell, fGridView.fSelections);
  2603.             END;
  2604.  
  2605.         IF LONGINT(clickedCell) <> LONGINT(fPrevCell) THEN
  2606.             BEGIN
  2607.             ComputeNewSelection(clickedCell);
  2608.             HighlightNewSelection;
  2609.  
  2610.             CopyRgn(fThisSelection, fPrevSelection);
  2611.             fPrevCell := clickedCell;
  2612.             END;
  2613.         END;
  2614.     TrackMouse := SELF;
  2615.     END;
  2616.  
  2617. {--------------------------------------------------------------------------------------------------}
  2618. {$S GVDoCommand}
  2619.  
  2620. PROCEDURE TCellSelectCommand.DoIt; OVERRIDE;
  2621.  
  2622.     BEGIN
  2623.     IF fGridView.fSingleSelection THEN
  2624.         fGridView.SelectCell(fThisSelection^^.rgnBBox.topLeft, kDontExtend, kDontHighlight, kSelect)
  2625.     ELSE
  2626.         fGridView.SetSelection(fThisSelection, kDontExtend, kDontHighlight, kSelect);
  2627.     END;
  2628.  
  2629. {--------------------------------------------------------------------------------------------------}
  2630. {$S GVFields}
  2631.  
  2632. PROCEDURE TCellSelectCommand.Fields(PROCEDURE DoToField(fieldName: Str255;
  2633.                                                         fieldAddr: Ptr;
  2634.                                                         fieldType: INTEGER)); OVERRIDE;
  2635.  
  2636.     BEGIN
  2637.     DoToField('TCellSelectCommand', NIL, bClass);
  2638.     DoToField('fGridView', @fGridView, bObject);
  2639.     DoToField('fShiftKey', @fShiftKey, bBoolean);
  2640.     DoToField('fCmdKey', @fCmdKey, bBoolean);
  2641.     DoToField('fDeselecting', @fDeselecting, bBoolean);
  2642.     DoToField('fAnchorCell', @fAnchorCell, bPoint);
  2643.     DoToField('fPrevCell', @fPrevCell, bPoint);
  2644.     DoToField('fThisSelection', @fThisSelection, bRgnHandle);
  2645.     DoToField('fPrevSelection', @fPrevSelection, bRgnHandle);
  2646.     DoToField('fDifference', @fDifference, bRgnHandle);
  2647.  
  2648.     INHERITED Fields(DoToField);
  2649.     END;
  2650.  
  2651. {--------------------------------------------------------------------------------------------------}
  2652. {$S GVDoCommand}
  2653.  
  2654. PROCEDURE TRCSelectCommand.ComputeNewSelection(VAR clickedCell: GridCell); OVERRIDE;
  2655.  
  2656.     VAR
  2657.         r:                    Rect;
  2658.  
  2659.     BEGIN
  2660.     IF fGridView.CanSelectCell(clickedCell) THEN
  2661.         BEGIN
  2662.         IF fGridView.fSingleSelection THEN
  2663.             SetRect(r, clickedCell.h, clickedCell.v, clickedCell.h + 1, clickedCell.v + 1)
  2664.         ELSE
  2665.             BEGIN
  2666.             Pt2Rect(fAnchorCell, clickedCell, r);
  2667.             r.right := r.right + 1;
  2668.             r.bottom := r.bottom + 1;
  2669.             END;
  2670.         RectRgn(fThisSelection, r);
  2671.         IF fCmdKey & (NOT fGridView.fSingleSelection) THEN
  2672.             IF fDeselecting THEN
  2673.                 DiffRgn(fPrevSelection, fThisSelection, fThisSelection)
  2674.             ELSE
  2675.                 UnionRgn(fPrevSelection, fThisSelection, fThisSelection);
  2676.         END;
  2677.     END;
  2678.  
  2679. {--------------------------------------------------------------------------------------------------}
  2680. {$S GVDoCommand}
  2681.  
  2682. FUNCTION TRCSelectCommand.TrackMouse(aTrackPhase: TrackPhase;
  2683.                                      VAR anchorPoint, previousPoint, nextPoint: VPoint;
  2684.                                      mouseDidMove: BOOLEAN): TCommand; OVERRIDE;
  2685.  
  2686.     VAR
  2687.         clickedCell:        GridCell;
  2688.         viewExtent:         VRect;
  2689.         clippedPoint:        VPoint;
  2690.  
  2691.     BEGIN
  2692.     IF mouseDidMove THEN
  2693.         BEGIN
  2694.         fGridView.GetExtent(viewExtent);
  2695.         clippedPoint := nextPoint;
  2696.         PinVRect(viewExtent, clippedPoint);
  2697.         clickedCell := fGridView.VPointToCell(clippedPoint);
  2698.         IF aTrackPhase = TrackPress THEN
  2699.             BEGIN
  2700.             ComputeAnchorCell(clickedCell);
  2701.             IF fCmdKey THEN
  2702.                 fDeselecting := PtInRgn(fAnchorCell, fGridView.fSelections);
  2703.             END;
  2704.  
  2705.         IF LONGINT(clickedCell) <> LONGINT(fPrevCell) THEN
  2706.             BEGIN
  2707.             IF (NOT fShiftKey) & (aTrackPhase <> TrackPress) THEN
  2708.                 BEGIN
  2709.                 ComputeAnchorCell(clickedCell);
  2710.                 IF fCmdKey THEN
  2711.                     fDeselecting := PtInRgn(fAnchorCell, fGridView.fSelections);
  2712.                 END;
  2713.             ComputeNewSelection(clickedCell);
  2714.             HighlightNewSelection;
  2715.  
  2716.             CopyRgn(fThisSelection, fPrevSelection);
  2717.             fPrevCell := clickedCell;
  2718.             END;
  2719.         END;
  2720.     TrackMouse := SELF;
  2721.     END;
  2722.  
  2723. {--------------------------------------------------------------------------------------------------}
  2724. {$S GVFields}
  2725.  
  2726. PROCEDURE TRCSelectCommand.Fields(PROCEDURE DoToField(fieldName: Str255;
  2727.                                                       fieldAddr: Ptr;
  2728.                                                       fieldType: INTEGER)); OVERRIDE;
  2729.  
  2730.     BEGIN
  2731.     DoToField('TRCSelectCommand', NIL, bClass);
  2732.     INHERITED Fields(DoToField);
  2733.     END;
  2734.  
  2735. {--------------------------------------------------------------------------------------------------}
  2736. {$S GVSelCommand}
  2737.  
  2738. PROCEDURE TRowSelectCommand.IRowSelectCommand(itsView: TGridView;
  2739.                                               theShiftKey, theCmdKey: BOOLEAN);
  2740.  
  2741.     BEGIN
  2742.     ICellSelectCommand(itsView, theShiftKey, theCmdKey);
  2743.     END;
  2744.  
  2745. {--------------------------------------------------------------------------------------------------}
  2746. {$S GVDoCommand}
  2747.  
  2748. PROCEDURE TRowSelectCommand.ComputeAnchorCell(VAR clickedCell: GridCell); OVERRIDE;
  2749.  
  2750.     BEGIN
  2751.     INHERITED ComputeAnchorCell(clickedCell);
  2752.     fAnchorCell.h := 1;
  2753.     END;
  2754.  
  2755. {--------------------------------------------------------------------------------------------------}
  2756. {$S GVDoCommand}
  2757.  
  2758. PROCEDURE TRowSelectCommand.ComputeNewSelection(VAR clickedCell: GridCell); OVERRIDE;
  2759.  
  2760.     BEGIN
  2761.     clickedCell.h := fGridView.fNumOfCols;
  2762.     INHERITED ComputeNewSelection(clickedCell);
  2763.     END;
  2764.  
  2765. {--------------------------------------------------------------------------------------------------}
  2766. {$S GVFields}
  2767.  
  2768. PROCEDURE TRowSelectCommand.Fields(PROCEDURE DoToField(fieldName: Str255;
  2769.                                                        fieldAddr: Ptr;
  2770.                                                        fieldType: INTEGER)); OVERRIDE;
  2771.  
  2772.     BEGIN
  2773.     DoToField('TRowSelectCommand', NIL, bClass);
  2774.     INHERITED Fields(DoToField);
  2775.     END;
  2776.  
  2777. {--------------------------------------------------------------------------------------------------}
  2778. {$S GVSelCommand}
  2779.  
  2780. PROCEDURE TColumnSelectCommand.IColumnSelectCommand(itsView: TGridView;
  2781.                                                     theShiftKey, theCmdKey: BOOLEAN);
  2782.  
  2783.     BEGIN
  2784.     ICellSelectCommand(itsView, theShiftKey, theCmdKey);
  2785.     END;
  2786.  
  2787. {--------------------------------------------------------------------------------------------------}
  2788. {$S GVDoCommand}
  2789.  
  2790. PROCEDURE TColumnSelectCommand.ComputeAnchorCell(VAR clickedCell: GridCell); OVERRIDE;
  2791.  
  2792.     BEGIN
  2793.     INHERITED ComputeAnchorCell(clickedCell);
  2794.     fAnchorCell.v := 1;
  2795.     END;
  2796.  
  2797. {--------------------------------------------------------------------------------------------------}
  2798. {$S GVDoCommand}
  2799.  
  2800. PROCEDURE TColumnSelectCommand.ComputeNewSelection(VAR clickedCell: GridCell); OVERRIDE;
  2801.  
  2802.     BEGIN
  2803.     clickedCell.v := fGridView.fNumOfRows;
  2804.     INHERITED ComputeNewSelection(clickedCell);
  2805.     END;
  2806.  
  2807. {--------------------------------------------------------------------------------------------------}
  2808. {$S GVFields}
  2809.  
  2810. PROCEDURE TColumnSelectCommand.Fields(PROCEDURE DoToField(fieldName: Str255;
  2811.                                                           fieldAddr: Ptr;
  2812.                                                           fieldType: INTEGER)); OVERRIDE;
  2813.  
  2814.     BEGIN
  2815.     DoToField('TColumnSelectCommand', NIL, bClass);
  2816.     INHERITED Fields(DoToField);
  2817.     END;
  2818.